C++ 中结构数组的 memset
我还有另一个 memset 问题。看来我正在编辑的代码可能有一些问题(或者在不同的文件中没有以相同的方式完成)
A::LRM las[9]; //A and LRM are both structures with BOOLS and INTS
memset(&las, 0, sizeof(las));
typedef Sec SecArray[16];
SecArray rad_array;
memset(rad_array, 0, sizeof(SecArray));
第二个示例似乎是正确的,因为 rad_array 与中的第一个位置相同大批。那么 sizeof(SecArray))
就有意义了。第一个对我来说似乎不正确。所有结构都只是 BOOL 和 INTS,其中没有任何动态。
我从我的另一篇关于 memset 的文章中了解到它遵循这种格式。
memset(“指向对象的指针”,“将其设置为什么”,“对象的大小”)
如果我的理论不正确,谁能告诉我这里到底发生了什么。
I have another memset question. It appears as if the code I am editing may have some issues (or it's not done the same way in different files)
A::LRM las[9]; //A and LRM are both structures with BOOLS and INTS
memset(&las, 0, sizeof(las));
typedef Sec SecArray[16];
SecArray rad_array;
memset(rad_array, 0, sizeof(SecArray));
The second example appears to be correct because rad_array
is the same as the first position in the array. Then the sizeof(SecArray))
would make sense. The first one doesn't seem correct to me. All structs are just BOOLs and INTS nothing dynamic in them.
My understanding from my other post about memset was that it followed this format.
memset("pointer to object", "what to set it to", "size of object")
Can anyone tell me what exactly is going on here if I am incorrect with my theory.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对
memset
的两次调用都是正确的。sizeof(las)
(或只是sizeof las
)和sizeof(SecArray)
都将返回整个数组的大小。如果您担心第一个参数,那么,两者都可以。指向整个数组 (
&las
) 的指针或指向第一个元素的指针(在本上下文中为rad_array
)与memset
的工作效果相同>。一般来说,关于
sizeof
的使用,我建议使用第一种方法,因为它是类型无关的。一个好的编程习惯是避免在语句中提及类型名称,即尽可能将类型名称限制在声明中。至于第一个参数,在数组的情况下,这是一个偏好问题,但一般来说,我会说,如果您有一个
T
类型的对象,并且您想通过使用将其填充为零
memset
,您通常会这样做,因为我不明白为什么数组应该是该规则的例外(特别是如果类型的确切性质隐藏在 typedef 名称后面)。无论
T
是数组类型、结构类型还是任何其他类型,上面的 memset(&t, ... 都会起作用。我不明白为什么人们应该突然删除&
只是因为T
是一种数组类型,恰恰相反,我会保留&
来保留。 最后,在 C++ 中,在这两种情况下,更好的方法是根本不使用 memset,而是直接使用
。
Both calls to
memset
are correct. Bothsizeof(las)
(or justsizeof las
) andsizeof(SecArray)
will return the size of the entire array.If you are worried about the first argument, then again, both will work. The pointer to the entire array (
&las
) or the pointer to the first element (rad_array
in this context) will work equally well withmemset
.In general, with regard to
sizeof
usage, I would recommend using the first approach, since it is type-independent. A good programming practice is to avoid mentioning type names in your statements, i.e. keep type names restricted to declarations as much as possible.As for the first argument, in case of an array it is a matter of preference, but in general I would say that if you have an object of type
T
and you want to fill it with zeros by using
memset
, you'd normally do it asI don't see why an array should be an exception from that rule (especially if the exact nature of the type is hidden behind a typedef-name). The above
memset(&t, ...
will work regardless of whetherT
is an array type, a struct type or any other type. I don't see why one should suddenly drop the&
just becauseT
is an array type. Quite the opposite, I'd keep that&
to keep the code as type-independent as possible.Finally, in C++ in both cases the better way to do it would be not to use
memset
at all and just doinstead.
您需要指定应设置的内存总长度。
memset 是一个 C 函数,它对参数一无所知。参数的实际含义是
所以这实际上更好:
您提供的两个示例实际上都可以工作,但它们很脆弱,因为数组很容易衰减为指针,之后它将无法按预期工作(例如,如果您将数组传递给执行 memset 的函数,或者使用 new 切换到动态分配)。
You need to specify the total length of memory that should be set.
memset is a C function, that knows nothing about arguments. The actual meaning of the arguments is
So this is actually better:
Both examples you provided will actually work, but they are fragile, since its is easy for an array to decay to a pointer, after which it will not work as expected (for example, if you passed the array into a function which does the memset, or switched to dynamic allocation using new).
memset 的最后一个参数不是对象的大小,而是“对象指针”指向的对象“数组”的大小。
假设您有:
memset 会将
ptr
和ptr+sizeof(*ptr)*length-1
之间的所有字节设置为value
。The last argument to memset is not the size of the object, it's the size of the "array" of objects pointed by "pointer to object".
Let's say you have:
memset will set all bytes between
ptr
andptr+sizeof(*ptr)*length-1
tovalue
.您的第一个示例将起作用,但我建议:
请注意,
A
是什么并不重要,A::LRM
是数据类型。但是
你不应该以这种方式初始化结构,因为虽然今天它只是BOOL和整数,明天它可能是,嗯,任何东西。。如果有人向
A::LRM
添加一个类,memset()
将覆盖其私有数据,您永远不会知道,直到为时已晚。Your first example will work, but I recommend:
Note that it doesn't matter what
A
is,A::LRM
is the datatype.BUT
You should not initialize structs that way, because although today it's nothing but BOOLs and ints, tomorrow it might be, well, anything. If someone adds a class to
A::LRM
,memset()
will overwrite its private data and you'll never know until it's too late.memset
用零字节填充内存。一般来说,这与将成员初始化为零不同。只要我们坚持标准 ISO C++(或 C,就此而言),唯一的保证就是 all-bits-0 是有效的char
或unsigned char< /code> 值等于
0
。即使对于整数类型,这也不一定是真的,因为它们允许在值位之外进行填充,并且这些位的全零可以是陷阱表示。这绝对不是将
float
或double
初始化为0.0
或指向null
的指针的正确方法。对于这些类型,现有的一致实现的全位零不是值0
。无论如何,通过使用空的聚合初始值设定项,您的代码可以写得更短,并且以完全可移植的方式编写:
这将对数组进行值初始化 - 反过来,对所有元素进行零初始化 - 对于 POD 结构,对所有字段进行零初始化。
当然,这假设
A::LRM
是一个 POD 结构。如果不是,那么 memset 更有可能破坏事物,并且您确实需要只使用它的构造函数,并分配给构造函数未初始化的任何字段。memset
fills the memory with zero bytes. It's not, in general, the same as initializing members to zero. So long as we're sticking to standard ISO C++ (or C, for that matter), the only guarantee you have is that all-bits-0 is a validchar
orunsigned char
value equal to0
. Even for integer types, this doesn't necessary have to be true, as they are allowed to have padding outside of value bits, and all-zero for those bits can be a trap representation.It's definitely not a proper way to initialize a
float
ordouble
to0.0
, or a pointer tonull
. There are existing conformant implementations for which all-bits-zero isn't value0
for those types.Anyway, your code can be written both much shorter, and in a fully portable way, by using an empty aggregate initializer:
This will value-initialize the array - which, in turn, zero-initializes all elements - which, for POD structs, zero-initializes all fields.
Of course, this assumes that
A::LRM
is a POD struct. If it's not, thenmemset
is even more likely to break things, though, and you really need to just use its constructor, and assign to any fields said constructor didn't initialize.