为什么这在C中对init a结构起作用?结构x_tmp={{{{0}};

为什么这在C中对init a结构起作用?结构x_tmp={{{{0}};,c,C,我一直在寻找这本书的编纂原因: struct x_ { char a[10]; int b; }; struct x_ tmp = {{{{0}}}}; 我们可能有一个较旧的gcc版本,所以{0}可能不起作用,应该使用{0},但在任何地方都看不到这个{{{0}}。 请参见此处的gcc错误: 谢谢 Peter初始化包含数组的结构时,可以初始化第一个元素,默认情况下将其余元素设置为0,也可以提供每个值的初始化。在这种情况下,使用字符串初始化或数组样式初始化为所有成员提供值,例如

我一直在寻找这本书的编纂原因:

struct x_ {
    char a[10];
    int  b;
};

struct x_ tmp = {{{{0}}}};
我们可能有一个较旧的gcc版本,所以{0}可能不起作用,应该使用{0},但在任何地方都看不到这个{{{0}}。 请参见此处的gcc错误:

谢谢
Peter

初始化包含数组的结构时,可以初始化第一个元素,默认情况下将其余元素设置为0,也可以提供每个值的初始化。在这种情况下,使用字符串初始化或数组样式初始化为所有成员提供值,例如

struct x_ tmp = { .a="" };  /* using string initialization of a  */

如果无法识别特定字段或为所有成员提供初始化,则在默认情况下将值初始化为0时,将为标量初始值设定项和缺少的字段初始值设定项周围的大括号生成编译器警告

使用/输出的示例


我将此问题解释为询问GCC是否正确地接受指定类型对象的指定初始值设定项。为了解决这个问题,我将引用C2011标准第6.7.9节

首先,以下内容既适用于整个结构的初始值设定项,也适用于第一个成员的内部初始值设定项:

[…]具有聚合或联合类型的对象的初始值设定项应为元素或命名成员的括号内初始值设定项列表

然后我们有:

每个括号内的初始值设定项列表都有一个关联的当前对象。当前对象的[…]子对象按照顺序进行初始化 对于当前对象的类型:按递增下标顺序排列的数组元素,按声明顺序排列的结构成员[…]

。。。后来

如果集合或联合包含属于集合或联合的元素或成员,则这些规则将递归应用于子集合或包含的联合。如果子集合或包含的并集的初始值设定项以左大括号开头,则由该大括号及其匹配的右大括号括起的初始值设定项将初始化子集合或包含的并集的元素或成员

其中,我们将整个{{{{{0}}}作为整个结构的初始值设定项,将{{{0}}作为其第一个成员a的初始值设定项,将{{0}}作为a[0]的初始值设定项。问题归结为最后一个配对是否有效。如果是,那么其他的也是有效的

这可能与以下事项有关:

标量的初始值设定项应为单个表达式,可以选择用大括号括起来

重点补充。这可以解释为指定[0]的初始值设定项可以用大括号括起来,即{0},因为[0]实际上是一个标量。我不相信这是预期的解释,但我不准备在这一点上指责GCC接受它

但是,我不接受{{0}}作为大括号中的单个表达式,因此我不接受它作为[0]的有效初始值设定项。我推测GCC接受它是因为不恰当地递归应用了允许标量初始值设定项用大括号括起来的规则

值得一提的是,默认情况下,GCC 4.4.7确实会发出两条关于构造的警告:

i.c:7: warning: braces around scalar initializer
i.c:7: warning: (near initialization for ‘tmp.a[0]’)
i.c:7: warning: braces around scalar initializer
i.c:7: warning: (near initialization for ‘tmp.a[0]’)

显然,有人认为额外的大括号是有问题的,但是GCC文档没有提到在支持的语言扩展中接受这种形式。那么,至少有一个文档错误。

MSVC说初始化器太多,您留下了一个语法错误no;在结构定义之后,@WeatherVane gcc也一样,只需修复它;您可以通过gcc-version来确定您拥有的gcc的确切版本。可能downvoter有完整性来识别示例中的技术错误,但很可能他们没有。问题不是关于正确的语法,尽管tmp={0};在本例中也是正确的,但是关于为什么gcc编译tmp={{{{{0}}};没有错误。我认为这是downvoteThe提交关于单个成员阵列初始化的错误报告的原因。没有任何参数表明结构示例{int foo[2];};可由结构示例ex={0}初始化;,但这不是问题中的tmp,这个答案并没有解决这个问题,这就是为什么结构x_tmp={{{{{0}}};如果您在默认情况下将值初始化为0时不阅读,我不会与您争论。为了回答为什么它会起作用,让你觉得否决投票更好——继续吧,我们只是不同意解释。
#include <stdio.h>

struct x_ {
    char a[10];
    int  b;
};

int main (void) {

    struct x_ tmp = { .a="" };  /* using string initialization of a  */
    struct x_ tmq = {{0},0};    /* using array initialization format */

    printf ("\n tmp.a : '%s', tmp.b : %d\n", tmp.a, tmp.b);
    printf ("\n tmq.a : '%s', tmq.b : %d\n", tmq.a, tmq.b);

    return 0;
}
$ ./bin/struct_init

 tmp.a : '', tmp.b : 0

 tmq.a : '', tmq.b : 0
i.c:7: warning: braces around scalar initializer
i.c:7: warning: (near initialization for ‘tmp.a[0]’)
i.c:7: warning: braces around scalar initializer
i.c:7: warning: (near initialization for ‘tmp.a[0]’)