在C ++中的结构数组上的memset

时间:2010-05-07 15:32:55

标签: 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("pointer to object", "what to set it to", "size of object")

如果我的理论不正确,有人能告诉我这里到底发生了什么。

5 个答案:

答案 0 :(得分:9)

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

如果你担心第一个参数,那么两个都会有效。指向整个数组(&las)的指针或指向第一个元素的指针(在此上下文中为rad_array)与memset同样适用。

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

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

T t;

并且您希望使用memset将其填充为0,通常按

进行填充
memset(&t, 0, sizeof t);

我不明白为什么数组应该是该规则的异常(特别是如果类型的确切性质隐藏在typedef-name后面)。无论memset(&t, ...是数组类型,结构类型还是任何其他类型,上述T都将起作用。我不明白为什么人们应该突然放弃&因为T是一个数组类型。恰恰相反,我会保留&以保持代码尽可能与类型无关。

最后,在两种情况下,在C ++中,更好的方法是不使用memset而只是

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

代替。

答案 1 :(得分:1)

您需要指定应设置的内存总长度 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切换到动态分配。

答案 2 :(得分:0)

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

假设你有:

memset(ptr, value, length);

memset会将ptrptr+sizeof(*ptr)*length-1之间的所有字节设置为value

答案 3 :(得分:0)

你的第一个例子可行,但我建议:

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

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

<强> BUT

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

答案 4 :(得分:0)

memset用零字节填充内存。通常,它与将成员初始化为零无关。只要我们坚持使用标准的ISO C ++(或C,就此而言),唯一的保证就是all-bits-0是一个有效的charunsigned char值等于{ {1}}。即使对于整数类型,也不一定必须如此,因为它们允许在值位之外填充,并且这些位的全零可以是陷阱表示。

这绝对不是将0float初始化为double或指向0.0的指针的正确方法。对于那些类型,存在符合所有的实现,其中所有位零不是值null

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

0

这将对数组进行值初始化 - 反过来,对所有元素进行零初始化 - 对于POD结构,对所有元素进行零初始化。

当然,这假设A::LRM las[9] = {}; 是POD结构。如果不是,那么A::LRM甚至更有可能破坏事物,你真的需要使用它的构造函数,并分配给构造函数没有初始化的任何字段。