未提及的struct fields *总是*初始化为零(即结构在堆栈中时)?

来自实验(在Clang和GCC中,使用-O2和-O0) 似乎在以下代码中

typedef struct foo_s { int i; int j; } foo_t; int main(void) { foo_t foo = {.i = 42}; ... 

foo.j自动为零。

是否由C99开始保证,还是编译器特定的实现细节?

注意:我甚至尝试将0xFF写入堆栈下方的无效内存,稍后给出了foo的地址。

更新:有几条评论声明这只是因为堆栈下方的内存恰好包含零。 以下代码确保不是这种情况,并且可能certificateGCC -O0正在归零内存。

-7和-6的偏移量取决于编译器。 他们需要在Clang中有所不同。

 typedef struct foo_s { int i; int j; } foo_t; int main(void) { int r; int *badstack0 = &r - 7; int *badstack1 = &r - 6; *badstack0 = 0xFF; // write to invalid ram, below stack printf("badstack0 %p, val: %2X\n", badstack0, *badstack0); *badstack1 = 0xEE; // write to invalid ram, below stack printf("badstack1 %p, val: %2X\n", badstack1, *badstack1); // struct test foo_t foo = {.i = 42}; printf("&foo.i %p\n", &foo.i); printf("&foo.j %p\n", &foo.j); printf("struct test: i:%ij:%i\n", foo.i, foo.j); return 0; } 

输出:

 badstack0 0x7fff221e2e80, val: FF badstack1 0x7fff221e2e84, val: EE &foo.i 0x7fff221e2e80 &foo.j 0x7fff221e2e84 struct test: i:42 j:0 

如果您提供任何初始化程序,则未明确提及的成员将被初始化为好像它们是静态的。 这是由6.7.9(19)中的标准保证的:

初始化应在初始化器列表顺序中进行,每个初始化器为特定子对象提供,覆盖同一子对象的任何先前列出的初始化器; 所有未明确初始化的子对象应与具有静态存储持续时间的对象隐式初始化

(我强调的重点)

如果您没有初始化任何成员,则所有成员的值都是不确定的。

C保证只要数组/结构/联合*的至少一个成员被明确初始化,那么所有其他成员将被初始化,就好像它们具有静态存储持续时间一样,如Daniel Fischer的答案所述。 换句话说,所有其他成员自动设置为零或NULL。

数组/结构/联合的存储类型不重要,无论它们是否具有自动或静态存储持续时间,它们都根据相同的规则进行初始化。

这不是C99或更高版本所特有的,C 一直有此要求。 所有符合C的编译器都遵循此规则,它是规范性的,不是实现定义的。

这与“调试版本”零出局无关。

事实上,这条规则解释了为什么你可以通过写作将整个数组归零

int array[100] = {0}

此代码表示“将第一个元素初始化为零,并将剩余的99个元素初始化为好像它们具有静态存储持续时间,即使它们也为零”。


(*)这三种类型在C标准中正式命名为“聚合类型”。