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

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

4

5 回答 5

11

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

如果您担心第一个参数,那么同样,两者都可以。指向整个数组 ( &las) 的指针或指向第一个元素的指针 (rad_array在此上下文中) 将同样适用于memset.

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

至于第一个参数,如果是数组,这是一个偏好问题,但总的来说,我会说,如果你有一个类型的对象T

T t;

并且你想用零填充它memset,你通常会这样做

memset(&t, 0, sizeof t);

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

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

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

反而。

于 2010-05-07T15:38:06.117 回答
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 切换到动态分配)。

于 2010-05-07T15:40:48.693 回答
0

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

假设您有:

memset(ptr, value, length);

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

于 2010-05-07T15:38:02.757 回答
0

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

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

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

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

于 2010-05-07T15:54:54.283 回答
0

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

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

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

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

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

当然,这是假设这A::LRM是一个 POD 结构。如果不是,那么memset更有可能破坏事情,你真的需要只使用它的构造函数,并将构造函数未初始化的任何字段分配给任何字段。

于 2010-05-07T18:59:53.493 回答