简体   繁体   English

结构零初始化方法

[英]Struct zero initialization methods

Is

struct datainfo info = { 0 };

the same as 同样的

struct datainfo info;
memset(&info, 0, sizeof(info));

What's the difference and which is better ? 有什么区别,哪个更好?

The first one is the best way by a country mile, as it guarantees that the struct members are initialised as they would be for static storage. 第一个是国家英里的最佳方式,因为它保证struct成员初始化为static存储。 It's also clearer. 它也更清晰。

There's no guarantee from a standards perspective that the two ways are equivalent, although a specific compiler may well optimise the first to the second, even if it ends up clobbering parts of memory discarded as padding . 从标准的角度来看,无法保证两种方式是等价的,尽管特定的编译器可能会优化第一种到第二种,即使它最终破坏了作为填充丢弃的部分内存。

(Note that in C++, the behaviour of the second way could well be undefined . Yes C is not C++ but a fair bit of C code does tend to end up being ported to C++.) (注意,在C ++中,第二种方式的行为很可能是未定义的 。是C不是C ++,但是相当一部分C代码往往最终被移植到C ++。)

Practically, those two methods are very likely to produce the same result. 实际上,这两种方法很可能产生相同的结果。 Probably on account of first being compiled into a call to memset itself on today's common platforms. 可能是因为首先在今天的通用平台上编译成对memset的调用。

From a language lawyer perspective, the first method will zero-initialize all the members of the of the structure, but there is nothing specified about the values any padding bytes may take (in the individual members, or the structure). 从语言律师的角度来看,第一种方法将零初始化结构的所有成员,但是没有任何关于任何填充字节可能采用的值的指定(在单个成员或结构中)。 While the the second method will zero out all the bytes. 而第二种方法将所有字节清零。 And to be even more precise, there is no guarantee that an all byte zero pattern is even an object's "zero" value. 更准确地说,不能保证全字节零模式甚至是对象的“零”值。

Since (if one knows their target platform) the two are pretty much equivalent in every way that counts for the programmer, you choose the one that best suits your preferences. 因为(如果一个人知道他们的目标平台)这两个在程序员方面几乎相同,你选择最适合你喜好的那个。

Personally, I favor the initialization over the call to memset . 就个人而言,我赞成对memset的调用进行初始化。 Because it happens at the point of declaration, and not in another statement, not to mention the portability aspect. 因为它发生在声明点,而不是在另一个声明中,更不用说可移植性方面了。 That makes it impossible to accidentally add code in between that makes the initialization not run (however unlikely that may be), or be faulty somehow. 这使得不可能在两者之间意外地添加代码,这使得初始化不会运行(但不太可能),或者以某种方式出错。 But some may say that memset is clearer, even to a programmer reading it later that is not aware of how {0} works. 但是有些人可能会说memset更清晰,即使是程序员稍后阅读它也不知道{0}是如何工作的。 I can't entirely disregard their argument either. 我也不能完全无视他们的论点。

As noted by others, the code is functionality equivalent. 正如其他人所指出的,代码是功能相同的。 Using the x86-64 gcc 8.3 compiler 使用x86-64 gcc 8.3编译器

The code: 编码:

#include <string.h>
main()
{
    struct datainfo { int i; };
    struct datainfo info;

    memset(&info, 0, sizeof(info));
}

produces the assembly: 生产组件:

main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        lea     rax, [rbp-4]
        mov     edx, 4
        mov     esi, 0
        mov     rdi, rax
        call    memset
        mov     eax, 0
        leave
        ret

while the code: 而代码:

main()
{
    struct datainfo { int i; };
    struct datainfo info = {0};
}

compiles to: 编译为:

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 0
        mov     eax, 0
        pop     rbp
        ret     

To my untrained eye, the two outputs are 11 instructions vs 6 instructions, so at least space is more efficient in the second implementation. 对于我未经训练的眼睛,两个输出是11个指令对6个指令,因此在第二个实现中至少空间更有效。 But as noted by others, the zero initialization method is much more explicit in its intent. 但正如其他人所指出的,零初始化方法的意图要明确得多。

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

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