在使用它之前memset一个结构是不错的风格?

时间:2016-05-08 23:06:36

标签: c linux signals

一旦我学会了信号,就会有一个处理信号的列表。

有一个struct sigaction,它是所有字节零的第一个memset(),其中包含以下行:

memset(&sa, 0, sizeof(sa));

我不确定为什么作者使用这种方法。

3 个答案:

答案 0 :(得分:4)

正如您已经被告知的那样,尝试从未初始化的结构成员中读取值会导致未定义的行为。这是无条件的坏事。因此,您有责任确保所有字段在读取之前进行初始化。

如果你知道结构的所有元素并且要明确地初始化它们,那么memset()就没有必要了。如果结构在您的控制之下,这是可以管理的 - 您只需要记住确保在向结构添加新成员时更新所有初始化发生的位置。如果你编写一个函数来做到这一点(想想C ++构造函数的C类似物',到第一个近似值),那么可以省略memset()。如果您在许多地方设置临时值,那么如果结构发生变化,您可能会遇到问题。

struct sigaction之类的情况下,它来自系统定义的标题,不同的系统可以(并且确实)向结构添加额外的字段 - 超出您计划初始化的字段。请注意,POSIX仅指定必须存在的字段;它没有规定字段的顺序,也没有强制要求结构中没有其他字段。但是,使用结构的额外(非POSIX)元素的函数不应该这样做,除非用户指示那些成员被初始化,通常带有一些显式标志,所以你不应该遇到问题 - 但它是比抱歉更安全。

因此,在您无法控制结构的情况下,memset()方法很容易被防御:保证将所有结构归零,即使是您不喜欢的位也是如此。了解 - 即使在编写代码后结构定义发生变化(增长)。

您可以使用struct sigaction sa = { 0 };struct sigaction *sap = calloc(sizeof(*sap), 1);来代替结构 - 它部分取决于您使用的一组编译器选项的繁琐程度(以及您使用的编译器的版本) ; GCC已经改变了它的行为,例如)。

您可能希望在POSIX标准中查找PTHREAD_MUTEX_INITIALIZER等宏,或者您可能更愿意忽略它们的存在。

答案 1 :(得分:1)

未初始化的变量包含不确定的值,使用它们通常会导致程序失败,因此在使用变量之前需要初始化变量。但是您不必使用memset来执行此操作,您可以使用初始化程序:

struct sigaction sa = {0};
这样就可以保存函数调用,并且代码的读者很容易发现它被初始化。

答案 2 :(得分:1)

当您在没有初始值设定项的情况下声明struct时,使用struct个成员中的任何一个而不首先分配它们是未定义的行为。如果您想将{0}放入struct的所有成员,memset提供了一个很好的方法。

如果您计划分配struct的所有成员,则无需拨打memset