是否已完全跟随子对象未定义行为的部分初始化?

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.bf.bar.r定义良好,还是这种初始化会导致未定义或未指定的行为?

The*_*ock 0

自从这个问题发布以来,C18 标准已经发布,并包含一些额外的说明,使答案完全清晰。

早在 2012 年就向标准机构提出了与此问题类似的澄清请求,并简要讨论了对语言的一些更改,这可能会使含义更清晰……最终决定 C11 语言已经是正确的,但是应该添加一个例子来澄清。

最后公开的 C17 草案第 6.7.9 节中的示例 12演示了子对象完全然后部分初始化时的正确行为,请注意,未显式覆盖的较大子对象的任何尾随值都应该保留(而不是被默认值覆盖) ),“因为隐式初始化不会覆盖显式初始化。”

所以正确的行为是打印“1,5,3”。