【问题标题】:Why is this valid C为什么这是有效的 C
【发布时间】:2013-06-28 23:22:38
【问题描述】:

我在reddit 上发现了这段代码。我原以为类型转换会导致它无效。

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

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

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

【问题讨论】:

  • 使用 gcc 我得到 24 个警告。好问题。我生活和学习:-)
  • 耶 gcc!至少你会收到警告。

标签: c


【解决方案1】:

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

每个用大括号括起来的初始化器列表都有一个关联的当前对象。当没有指定时,当前对象的子对象根据当前对象的类型按顺序初始化:数组元素按下标递增顺序,结构成员按声明顺序,联合的第一个命名成员。

这解释了为什么你得到 1、7 和 9 - 当前对象由这些大括号设置。那么至于为什么它不关心额外的东西,来自第20段:

... 仅考虑列表中足够的初始化器来考虑子聚合的元素或成员或包含的联合的第一个成员;剩下的任何初始化器都将用于初始化当前子聚合或包含的联合所属的聚合的下一个元素或成员。

【讨论】:

  • 您介意分享您引用的标准的网址吗?
  • 我将其称为“标准中的错误”。或者也许是“特征”;毕竟,它已经记录在案了!
  • 他们可能想保持一些奇怪的旧代码合法。
  • @torek It's not a bug! It's an undocumented feature! ~ 流行的编程借口/引用。
  • 对我的口味来说不够定义,我不得不说... =)
【解决方案2】:
  int a[3] = { { {1, 2}, {3, 4}, 5, 6 }, {7, 8}, {9}, 10 };

无效。

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

(C99, 6.7.8p1) “任何初始化程序都不应尝试为未包含在正在初始化的实体中的对象提供值。”

a 初始化器中的最后一个元素 10 尝试为未包含在正在初始化的实体中的对象提供值。

【讨论】:

  • 我很想听到关于您引用的参考文献和 Carl 引用的第二个参考文献的不同断言的良好辩论。似乎是标准内的明显冲突,这可能会导致编译器实现的差异,直到它得到解决。 +1 指出差异。
猜你喜欢
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
相关资源
最近更新 更多