是
struct datainfo info = { 0 };
同样的
struct datainfo info;
memset(&info, 0, sizeof(info));
有什么区别,哪个更好?
第一个是国家英里的最佳方式,因为它保证struct
成员初始化,因为它们将用于static
存储。它也更清晰。
从标准的角度来看,无法保证这两种方式是等价的,尽管特定的编译器可以很好地优化第一种到第二种,即使它最终破坏了作为填充丢弃的部分内存。
(注意,在C ++中,第二种方式的行为很可能是未定义的。是C不是C ++,但是相当一部分C代码往往最终被移植到C ++。)
实际上,这两种方法很可能产生相同的结果。可能是因为在今天的通用平台上首次编译成对memset
本身的调用。
从语言律师的角度来看,第一种方法将零初始化结构的所有成员,但是没有任何关于任何填充字节可能采用的值的指定(在单个成员或结构中)。而第二种方法将所有字节清零。更准确地说,不能保证全字节零模式甚至是对象的“零”值。
因为(如果一个人知道他们的目标平台)这两个在程序员方面几乎相同,你选择最适合你喜好的那个。
就个人而言,我赞成通过调用memset
进行初始化。因为它发生在声明点,而不是在另一个声明中,更不用说可移植性方面了。这使得不可能在两者之间意外地添加代码,这使得初始化不会运行(但不太可能),或者以某种方式出错。但有些人可能会说memset
更清晰,甚至对程序员稍后阅读它并不知道{0}
如何工作。我也不能完全无视他们的论点。
正如其他人所指出的,代码是功能相同的。使用x86-64 gcc 8.3编译器
代码:
#include <string.h>
main()
{
struct datainfo { int i; };
struct datainfo info;
memset(&info, 0, sizeof(info));
}
生产组件:
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
而代码:
main()
{
struct datainfo { int i; };
struct datainfo info = {0};
}
编译为:
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
mov eax, 0
pop rbp
ret
对于我未经训练的眼睛,两个输出是11个指令对6个指令,因此在第二个实现中至少空间更有效。但正如其他人所指出的,零初始化方法的意图要明确得多。