用{0}或{'\ 0'}初始化结构之间有什么区别?

时间:2018-09-02 10:22:50

标签: c struct initialization

一个工作同事建议使用{'\0'}而不是{0}初始化结构,因为他解释说0被认为是int,因此至少4个字节。因此,如果结构不是4的倍数,则将结构初始化为0可能会留下一些未初始化为0的字节,而由于\0是大小为1个字节的ASCII字符,它将初始化一个不论大小如何,结构都为零。

话虽如此,但我几乎从未见过使用{'\0'}进行初始化。

我的问题是,用{0}初始化结构是否足够?是否足够,因为大多数编译器会自动用0填充不是4的倍数的字节,还是因为C做到了?

2 个答案:

答案 0 :(得分:10)

不,没有区别。

对于一个,'\0'不是“一个字节”;在C语言中,字符常量的类型为int,因此'\0'0在每种情况下都是100%等效的。 (您可以使用sizeof进行检查:sizeof 0sizeof '\0'会产生相同的值,通常为4或8。)

另一个原因在C的初始化规则(在C99中为 6.7.8初始化)中进行了解释:

  

[...]

     
      
  1. 否则,具有聚合或联合类型的对象的初始化程序应是用括号括起来的元素或命名成员的初始化程序列表。

  2.   
  3. 每个用大括号括起来的初始化程序列表都有一个关联的当前对象。当没有   存在指定,当前对象的子对象按以下顺序初始化   到当前对象的类型:下标顺序递增的数组元素,结构   成员按声明顺序排列,并且是联盟的第一个命名成员。 [...]

  4.   

这表示初始化列表的成员用于按顺序初始化结构或数组的字段;有多少字节都没关系。

如果你写

struct foo { double x; };
struct foo var = { 0 };

然后使用0(第一个初始化值,类型为int)来初始化第一个结构字段(x,类型为double)。就像您写了double x = 0。结果是0的值从int隐式转换为double并存储在变量中。

此外,如果初始化程序少于struct或array元素,则此规则开始执行:

  
      
  1. 如果用大括号括起来的列表中的初始化程序少于元素或成员   用来初始化已知数组的字符串文字中的总计或更少的字符   大于数组中元素的大小,则其余部分应为   隐式初始化与具有静态存储持续时间的对象相同。
  2.   

那么隐式初始化如何与静态对象一起使用?

  
      
  1. 如果具有自动存储期限的对象未显式初始化,则其值为   不定。如果具有静态存储持续时间的对象未明确初始化,   然后:

         
        
    • 如果具有指针类型,则将其初始化为空指针;
    •   
    • 如果具有算术类型,则将其初始化为(正数或无符号)零;
    •   
    • 如果是聚合,则根据这些规则(递归)初始化每个成员;
    •   
    • 如果是联合,则将根据这些规则(递归)初始化第一个命名成员。
    •   
  2.   

这意味着数组或结构的所有未明确初始化的成员都隐式设置为0。

答案 1 :(得分:0)

是的,用{0}初始化结构就足够了。理解编译器不会基于初始化将内存分配给struct。不管是否填充某些值的结构都将始终需要相同的内存。

例如

#include <stdio.h>

struct A {
    char a;
};

struct B {
    int b;
};

int main(void) {
    struct A b = {'\0'};
    struct A c = {0};
    printf("%zu %zu\n",sizeof(b),sizeof(c));

    struct B ab = {'\0'};
    struct B ac = {0};
    printf("%zu %zu\n",sizeof(ab),sizeof(ac));

    return 0;
}

答案总是相同的,而与分配方式无关。