2016-08-30 60 views
0

我一直在找周围为什么这编译:为什么在C中为init结构工作? struct x_ tmp = {{{{}}}};

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

struct x_ tmp = {{{{0}}}}; 

我们可能有一个旧版本的编译,所以{0}可能无法正常工作和{{0}}应该被使用,但没有看到这{{{{0}}}}任何地方。 参见GCC错误这里:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119

由于 彼得

+0

MSVC说“太多初始化程序”,并且在'struct'定义之后留下了语法错误no';'。 –

+0

@WeatherVane gcc,只需修复它;) – Serge

+0

您可以通过'gcc --version'确切确定哪个版本的gcc。 –

回答

-2

当初始化包含数组的结构,既可以初始化的第一个元素(具有设置为0默认的其余部分),也可以提供的初始化每个值。在这种情况下,使用字符串初始化为a阵列样式初始化为所有成员提供值,例如,

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

struct x_ tmp = {{0},0}; /* using array initialization format */ 

未能识别某一特定领域,或提供一个初始化的所有成员都将产生围绕一个标量初始化和缺场的初始化括号编译器警告,同时默认初始化值为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 
+0

也许downvoter将具有完整性来识别示例中的技术不准确性,但是他们可能不会。 –

+0

问题不是关于正确的语法,尽管'tmp = {0};'在这种情况下也是正确的,但是为什么'gcc'没有编译'tmp = {{{{}}}};'没有错误。我认为这是downvote的原因 – Serge

+0

该bug报告是关于单成员数组初始化提交的。没有任何参数可以通过'struct example ex = {0};'初始化'struct example {int foo [2];};',但在问题中不是'tmp'。 –

1

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

首先,以下既适用于初始化为整体结构,并内的第一构件的初始化:

[...]的初始值设定为一个对象,其具有聚合或联合类型应是元素或命名成员的初始化符的大括号包含列表。

我们则有:

每个括号内的初始化列表中有相关​​的当前对象。当前对象的子对象按照 的顺序初始化为当前对象的类型:数组元素以下标顺序递增,结构成员以声明顺序[...]。

......后来......

如果聚集或联合包含的元素或成员是聚集或工会,这些规则递归适用于subaggregates或包含工会。如果子集或包含的联合的初始化器以左大括号开始,那么大括号和其右括号所包含的初始化器将初始化子集或包含的联合的元素或成员。

在这些,我们已经建立了作为一个初始化整个结构的整体{{{{0}}}}{{{0}}}作为其第一个成员,a一个初始化,并{{0}}作为a[0]的初始化。问题归结为最后的配对是否有效。如果是,那么其他人也是有效的。

这可能带有对此事:

为标量的初始化应是一个单一的表达,任选包含在括号

(强调增加)。这可以解释为指定a[0]的初始值设定项可以用大括号括起来,即{0},因为a[0]确实是一个标量。我不相信这就是预期的解释,但我现在不会准备好接受GCC的过错。

但是,我不接受{{0}}作为大括号中的单个表达式,因此我不接受它是a[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]’) 

显然,然后,有人认为额外的括号是有问题的,但海湾合作委员会的文件没有提到接受这在支持的语言扩展中形成。那么,至少有一个文档错误。