非显式初始化成员的结构总是0,其部分成员被初始化?

时间:2016-03-03 07:37:33

标签: c gcc

我正在验证struct成员初始化。编译器为gcc 4.8.5,代码如下:

#include <stdio.h>

typedef struct
{
        int m1;
        int m2;
} A;

int main(void) {
        A a;
        A b = {.m1 =1};
        A c = {1};

        printf("%d, %d\n", a.m1, a.m2);
        printf("%d, %d\n", b.m1, b.m2);
        printf("%d, %d\n", c.m1, c.m2);
        return 0;
}

执行它的结果是:

-1498088800, 32765
1, 0
1, 0

汇编代码是:

0x0000000000400530 <+0>:     push   %rbp
0x0000000000400531 <+1>:     mov    %rsp,%rbp
0x0000000000400534 <+4>:     sub    $0x30,%rsp
0x0000000000400538 <+8>:     movq   $0x0,-0x20(%rbp)
0x0000000000400540 <+16>:    movl   $0x1,-0x20(%rbp)
0x0000000000400547 <+23>:    movq   $0x0,-0x30(%rbp)
0x000000000040054f <+31>:    movl   $0x1,-0x30(%rbp)
0x0000000000400556 <+38>:    mov    -0xc(%rbp),%edx
0x0000000000400559 <+41>:    mov    -0x10(%rbp),%eax
0x000000000040055c <+44>:    mov    %eax,%esi
0x000000000040055e <+46>:    mov    $0x400640,%edi
0x0000000000400563 <+51>:    mov    $0x0,%eax
0x0000000000400568 <+56>:    callq  0x400410 <printf@plt>

从汇编代码:

0x0000000000400538 <+8>:     movq   $0x0,-0x20(%rbp)
0x0000000000400540 <+16>:    movl   $0x1,-0x20(%rbp)
0x0000000000400547 <+23>:    movq   $0x0,-0x30(%rbp)
0x000000000040054f <+31>:    movl   $0x1,-0x30(%rbp)

我可以看到我是否初始化结构的部分成员,其他成员默认设置为0。这是否符合C规范?或者只是依赖于编译器?

2 个答案:

答案 0 :(得分:4)

他们被认为是零。

引自N1256 6.7.8初始化

  

10如果没有显式初始化具有自动存储持续时间的对象,则其值为   不定。如果未明确初始化具有静态存储持续时间的对象,   然后:
   - 如果它有指针类型,则将其初始化为空指针;
   - 如果它具有算术类型,则将其初始化为(正或无符号)零;
   - 如果是聚合,则根据这些规则初始化(递归)每个成员;
   - 如果它是一个联合,则根据这些初始化(递归)第一个命名成员   规则。

     

21如果括号括起的列表中的初始值设定项少于元素或成员   用于初始化已知数组的字符串文字中的聚合或更少字符   大小比数组中的元素大,其余的聚合应该是   隐式初始化与具有静态存储持续时间的对象相同。

答案 1 :(得分:0)

如果使用大括号初始化并且只有部分初始化结构,则其余部分的设置方式与结构实例具有静态存储持续时间的方式完全相同。

请注意,由于printf("%d, %d\n", a.m1, a.m2);未初始化,a的行为未定义。虽然引用输出程序集有点可以减轻你的情况。