简体   繁体   English

使用结构记忆结构好吗?

[英]Is it good style to memset a struct before using it?

Once I learned signals and there was a listing with handling signals. 一旦我学会了信号,便有了处理信号的清单。

There was a struct sigaction which was first memset() to all bytes zero with the following line: 有一个struct sigaction ,它是第一个memset()到所有字节为零的以下行:

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

And I'm not sure why author uses this approach. 而且我不确定为什么作者使用这种方法。

As you've already been told, trying to read values from uninitialized members of a structure leads to undefined behaviour. 正如您已经被告知的那样,尝试从结构的未初始化成员中读取值会导致未定义的行为。 That is unconditionally bad. 那是无条件的坏。 Therefore, it is incumbent upon you to ensure that all fields are initialized before they're read. 因此,您有责任确保在读取所有字段之前对其进行初始化。

If you know all the elements of the structure and are going to initialize them explicitly, then the memset() is not necessary. 如果您知道该结构的所有元素并打算显式初始化它们,则不需要memset() This can be manageable if the structure is under your control — you just have to remember to ensure that all the places where initialization takes place are updated when you add new members to the structure. 如果结构处于您的控制之下,那么这是可以管理的-您只需记住要确保在向结构中添加新成员时,所有初始化发生的位置都得到了更新。 If you write a function to do that (think 'C analogue of C++ constructor', to a first approximation), then the memset() can be left out. 如果编写一个函数来做到这一点(想想“ C ++构造函数的C类似物”,第一次近似),那么memset() If you set the values ad hoc in many places, you've probably got problems if the structure changes. 如果您在许多地方临时设置值,则结构更改可能会出现问题。

In the case of something like struct sigaction , it is from a system-defined header, and different systems can (and do) add extra fields to the structure — over and above the ones you plan to initialize. 对于诸如struct sigaction类的东西,它来自系统定义的头文件,并且不同的系统可以(并且确实)向结构中添加额外的字段-除了计划初始化的字段。 Note that POSIX only specifies the fields that must be present; 请注意,POSIX仅指定必须存在的字段。 it does not dictate the order of the fields, nor does it mandate that there are no other fields in the structure. 它不决定字段的顺序,也不要求结构中没有其他字段。 However, the functions using the extra (non-POSIX) elements of the structure should not do so unless the user indicates that those members are initialized, usually with some explicit flag, so you shouldn't run into problems — but it is better safe than sorry. 但是,使用结构的多余(非POSIX)元素的函数不应该这样做,除非用户指示通常使用一些显式标志初始化那些成员,这样就不会遇到问题-但这样做更安全比对不起。

Consequently, in contexts where you don't have control over the structure, the memset() approach is readily defensible: it is guaranteed to zero all of the structure, even the bits you don't know about — even if the structure definition changes (grows) after the code is written. 因此,在您无法控制结构的情况下, memset()方法很容易辩护:即使结构定义发生了变化,也可以保证将所有结构(即使您不知道的位)都清零。 (编写代码后)。

You may be able to use struct sigaction sa = { 0 }; 您可能可以使用struct sigaction sa = { 0 }; or struct sigaction *sap = calloc(sizeof(*sap), 1); struct sigaction *sap = calloc(sizeof(*sap), 1); to zero the structure instead — it depends in part on how fussy a set of compiler options you use (and also the version of the compiler you use; GCC has changed its behaviour over time, for example). 将结构改为零,这部分取决于您使用的一组编译器选项的复杂程度(以及所使用的编译器的版本;例如,GCC随着时间的推移已更改其行为)。

You might want to look up macros such as PTHREAD_MUTEX_INITIALIZER in the POSIX standard — or you may prefer to ignore their existence altogether. 您可能想要在POSIX标准中查找诸如PTHREAD_MUTEX_INITIALIZER宏,或者您可能希望完全忽略它们的存在。

Uninitialized variable contains indeterminate values, use of them are often cause of program failures, so you will need to initialize a variable before use it. 未初始化的变量包含不确定的值,使用它们通常是导致程序失败的原因,因此您需要在使用变量之前对其进行初始化。 But you don't have to use memset to do it, you can use initializer: 但是您不必使用memset即可,可以使用初始化器:

struct sigaction sa = {0};

this way a function call is saved, and it's easy for the reader of the code to spot it is initialized. 这样,可以保存函数调用,并且代码阅读器可以轻松地发现它已被初始化。

When you declare a struct without an initializer, it is undefined behavior to use any of that struct 's members without assigning them first. 当您声明没有初始化程序的struct ,使用该struct的任何成员而不先分配它们是未定义的行为。 If you would like to put zeros into all members of the struct , memset provides a good approach to do so. 如果您希望将零放入struct所有成员中,那么memset提供了一种很好的方法。

If you plan to assign all members of the struct anyway, the call to memset is unnecessary. 如果您仍然计划分配该struct所有成员,则无需调用memset

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM