是
struct datainfo info = { 0 };
与
相同struct datainfo info;
memset(&info, 0, sizeof(info));
有什么区别,哪个更好?
答案 0 :(得分:6)
第一个方法是按国家/地区英里划分的最佳方法,因为它可以确保struct
成员被初始化,就像它们用于static
存储一样。 也更清晰。
从标准的角度来看,虽然特定的编译器可能会破坏第一种到第二种,即使最终导致破坏了作为 padding 丢弃的部分内存,但从标准的角度看,这两种方法都是等效的。
(请注意,在C ++中,第二种方式的行为很可能是 undefined 。是的,C不是C ++,但是相当一部分C代码确实倾向于最终移植到C ++。)
答案 1 :(得分:4)
实际上,这两种方法很可能产生相同的结果。可能是由于首先在当今的通用平台上被编译为对memset
本身的调用。
从语言律师的角度来看,第一种方法将对结构的所有成员进行零初始化,但未指定任何 padding 字节可能采用的值(在单个成员中) ,或结构)。第二种方法会将所有所有字节清零。更准确地说,不能保证全字节零模式甚至是对象的“零”值。
由于(如果一个人知道他们的目标平台)这两者在程序员的每一个方面都非常相似,因此您选择最适合您的偏好的一个。
个人而言,我更喜欢初始化而不是对memset
的调用。因为它发生在声明时,而不是在另一个声明中发生,更不用说可移植性了。这使得不可能在意外之间添加使初始化无法运行(无论如何不太可能)或以某种方式出错的代码。但是有些人可能会说memset
更清楚,即使是后来阅读它的程序员也不知道{0}
是如何工作的。我也不能完全无视他们的论点。
答案 2 :(得分:1)
正如其他人所指出的,该代码在功能上是等效的。 使用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条指令,因此至少在第二种实现中空间更有效。但是,正如其他人所指出的,零初始化方法的意图更加明确。