结构零初始化方法

时间:2019-04-08 06:35:43

标签: c memset

struct datainfo info = { 0 };

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

有什么区别,哪个更好?

3 个答案:

答案 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条指令,因此至少在第二种实现中空间更有效。但是,正如其他人所指出的,零初始化方法的意图更加明确。