The*_*ock 7 c initialization undefined-behavior
考虑以下结构初始化:
#include<stdio.h>
struct bar {
int b;
int a;
int r;
};
struct foo {
struct bar bar;
};
int main(int argc, char **argv) {
struct bar b = {1, 2, 3};
struct foo f = {.bar = b, .bar.a = 5 };
// should this print "1, 5, 3", "1, 5, 0", or "0, 5, 0"?
// clang on Mac prints "1, 5, 3", while gcc on Ubuntu prints "0, 5, 0"
printf("%d, %d, %d\n", f.bar.b, f.bar.a, f.bar.r);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
C11标准似乎在描述6.7.9节中应该预期的行为方面做得相当糟糕,但似乎认为它做了一个合理的工作,因为在这种情况下我也没有看到关于未定义行为的任何警告.
在实践中,似乎行为要么没有标准化,要么标准被至少一个常见的编译器违反,在Mac上产生"1,5,3"的clang/llvm 8.0.0和在Ubuntu产生"0"的gcc 5.4 ,5,0".
根据C标准,此时应该f.bar.b和f.bar.r定义良好,还是这种初始化会导致未定义或未指定的行为?
自从这个问题发布以来,C18 标准已经发布,并包含一些额外的说明,使答案完全清晰。
早在 2012 年就向标准机构提出了与此问题类似的澄清请求,并简要讨论了对语言的一些更改,这可能会使含义更清晰……最终决定 C11 语言已经是正确的,但是应该添加一个例子来澄清。
最后公开的 C17 草案第 6.7.9 节中的示例 12演示了子对象完全然后部分初始化时的正确行为,请注意,未显式覆盖的较大子对象的任何尾随值都应该保留(而不是被默认值覆盖) ),“因为隐式初始化不会覆盖显式初始化。”
所以正确的行为是打印“1,5,3”。