2012-03-20 117 views
47

我在reddit上遇到过这段代码。我原以为类型转换会导致这种无效。为什么这个有效的C

int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 }; 

在clang上,我在标量初始值设定项中得到了一些关于过量元素和大括号的警告。但a的内容是[1, 7, 9]

这实际上是否合法,如果是的话,有人可以解释究竟发生了什么吗?

+5

+1,真是有趣。 – ApprenticeHacker 2012-03-20 17:50:11

+4

使用gcc我得到24个警告。很好的问题。我活着学习:-) – gbulmer 2012-03-20 18:56:47

+1

Yay gcc!至少你会收到警告。 – boatcoder 2012-03-30 14:15:20

回答

28

多余的元素被忽略。有两部分6.7.8初始化你关心的。首先,从第17段开始:

每个大括号包含的初始化程序列表都有一个关联的当前对象。如果没有指定,则根据当前对象的类型对当前对象的子对象进行初始化:按照下标顺序递增的数组元素,按声明顺序的结构成员以及联合的第一个已命名成员。

这一个解释了为什么你会得到1,7和9 - 当前对象由大括号设置。那么,为什么它不关心群众演员,从第20段:

...只有从列表中足够的初始化被带到占子聚集的元素或成员或的第一个成员包含工会;任何剩余的初始化器都将初始化当前的子聚集或包含的联合所属的聚合的下一个元素或成员。

+0

但是为什么?为什么在没有struct/union/class类型的情况下传递嵌套元素是有效的? – ams 2012-03-20 17:47:34

+1

你介意分享你引用的标准的网址吗? – dldnh 2012-03-20 17:52:54

+0

[PDF链接](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf) – 2012-03-20 17:53:59

2
int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 }; 

是无效的。

正是出于同样的原因int b[1] = {1, 2};无效是无效的:因为C99说

(C99,6.7.8p1)“没有初始化将试图提供没有包含的实体中的对象的值初始化“。

的最后一个元素10a初始化试图提供不包含在所述实体被初始化的对象的值。

+0

我希望听到关于您引用的参考文献所提出的不同论断以及卡尔引用的第二个参考文献的良好辩论。似乎是标准中的一个明显冲突,这可能会导致编译器实现方面的差异,直到解决问题。 +1指出差异。 – ryyker 2014-06-18 19:23:00