C++ 中结构数组的 memset

发布于 2024-09-01 10:11:03 字数 538 浏览 13 评论 0原文

我还有另一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

时光沙漏 2024-09-08 10:11:03

memset 的两次调用都是正确的。 sizeof(las)(或只是sizeof las)和sizeof(SecArray)都将返回整个数组的大小。

如果您担心第一个参数,那么,两者都可以。指向整个数组 (&las) 的指针或指向第一个元素的指针(在本上下文中为 rad_array)与 memset 的工作效果相同>。

一般来说,关于 sizeof 的使用,我建议使用第一种方法,因为它是类型无关的。一个好的编程习惯是避免在语句中提及类型名称,即尽可能将类型名称限制在声明中。

至于第一个参数,在数组的情况下,这是一个偏好问题,但一般来说,我会说,如果您有一个 T 类型的对象,

T t;

并且您想通过使用将其填充为零memset,您通常会这样做,因为

memset(&t, 0, sizeof t);

我不明白为什么数组应该是该规则的例外(特别是如果类型的确切性质隐藏在 typedef 名称后面)。无论 T 是数组类型、结构类型还是任何其他类型,上面的 memset(&t, ... 都会起作用。我不明白为什么人们应该突然删除 & 只是因为 T 是一种数组类型,恰恰相反,我会保留 & 来保留。 最后,在 C++ 中,在这两种情况下,

更好的方法是根本不使用 memset,而是直接使用

A::LRM las[9] = {};
SecArray rad_array = {};

Both calls to memset are correct. Both sizeof(las) (or just sizeof las) and sizeof(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 with memset.

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

T t;

and you want to fill it with zeros by using memset, you'd normally do it as

memset(&t, 0, sizeof t);

I 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 whether T is an array type, a struct type or any other type. I don't see why one should suddenly drop the & just because T 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 do

A::LRM las[9] = {};
SecArray rad_array = {};

instead.

感情旳空白 2024-09-08 10:11:03

您需要指定应设置的内存总长度。
memset 是一个 C 函数,它对参数一无所知。参数的实际含义是

memset("pointer to memory", "what to set each byte to", "number of bytes to set")

所以这实际上更好:

A::LRM las[9]; //A and LRM are both structures with BOOLS and INTS
memset(&las, 0, sizeof(A::LRM)*9);

typedef Sec SecArray[16];
SecArray rad_array;
memset(rad_array, 0, sizeof(Sec)*16);

您提供的两个示例实际上都可以工作,但它们很脆弱,因为数组很容易衰减为指针,之后它将无法按预期工作(例如,如果您将数组传递给执行 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

memset("pointer to memory", "what to set each byte to", "number of bytes to set")

So this is actually better:

A::LRM las[9]; //A and LRM are both structures with BOOLS and INTS
memset(&las, 0, sizeof(A::LRM)*9);

typedef Sec SecArray[16];
SecArray rad_array;
memset(rad_array, 0, sizeof(Sec)*16);

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).

樱娆 2024-09-08 10:11:03

memset 的最后一个参数不是对象的大小,而是“对象指针”指向的对象“数组”的大小。

假设您有:

memset(ptr, value, length);

memset 会将 ptrptr+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(ptr, value, length);

memset will set all bytes between ptr and ptr+sizeof(*ptr)*length-1 to value.

如梦 2024-09-08 10:11:03

您的第一个示例将起作用,但我建议:

A::LRM las[9]; 
memset(las, 0, sizeof(las)); // <== no ampersand needed

请注意,A 是什么并不重要,A::LRM 是数据类型。

但是

你不应该以这种方式初始化结构,因为虽然今天它只是BOOL和整数,明天它可能是,嗯,任何东西。。如果有人向 A::LRM 添加一个类,memset() 将覆盖其私有数据,您永远不会知道,直到为时已晚。

Your first example will work, but I recommend:

A::LRM las[9]; 
memset(las, 0, sizeof(las)); // <== no ampersand needed

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.

妄司 2024-09-08 10:11:03

memset 用零字节填充内存。一般来说,这与将成员初始化为零不同。只要我们坚持标准 ISO C++(或 C,就此而言),唯一的保证就是 all-bits-0 是有效的 charunsigned char< /code> 值等于 0。即使对于整数类型,这也不一定是真的,因为它们允许在值位之外进行填充,并且这些位的全零可以是陷阱表示。

这绝对不是将 floatdouble 初始化为 0.0 或指向 null 的指针的正确方法。对于这些类型,现有的一致实现的全位零不是值 0

无论如何,通过使用空的聚合初始值设定项,您的代码可以写得更短,并且以完全可移植的方式编写:

A::LRM las[9] = {};

这将对数组进行值初始化 - 反过来,对所有元素进行零初始化 - 对于 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 valid char or unsigned char value equal to 0. 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 or double to 0.0, or a pointer to null. There are existing conformant implementations for which all-bits-zero isn't value 0 for those types.

Anyway, your code can be written both much shorter, and in a fully portable way, by using an empty aggregate initializer:

A::LRM las[9] = {};

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, then memset 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文