为什么 const 限定变量被接受为 gcc 的初始值设定项?

2023-11-26

在最新版本的 gcc(或 clang)中编译此代码时-std=c17 -pedantic-errors -Wall -Wextra

static const int y = 1;
static int x = y;

然后我没有收到编译器诊断消息,即使我相当确定这不是有效的 C,而是违反了约束。我们可以通过查看 C17 6.7.9/4 来证明它是不合格的:

约束条件
...
具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式都应是常量表达式或字符串文字。

然后是关于常量表达式的定义,在本例中是整数常量表达式(6.6):

整数常量表达式应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数常量的 sizeof 表达式、_Alignof 表达式以及作为强制转换的直接操作数的浮点常量的操作数。

最后是关于整数常量的定义(6.4.4.1/2):

整数常量以数字开头,但没有句点或指数部分。它可能有一个指定其基数的前缀和一个指定其类型的后缀。

Thus a const int变量不是整型常量,也不是整型常量表达式。因此不是一个有效的初始化器。这之前已经讨论过(例如here)并且我认为已经确定这是不合格的。然而,我的问题是:

为什么 gcc 即使在严格模式下也选择不合规?

clang 显然一直是不合规的,但是 gcc 从 7.3 版本中的合规变成了 8.0 及以上版本中的不合规。 gcc 7.3 及更早版本给出“错误:初始化元素不是常量”,即使在默认模式下也没有-pedantic-errors.

对于这个信息,似乎已经做出了某种积极的、有意识的决定。为什么它在 gcc 中被完全删除以及为什么他们不保留它在严格模式下编译时的原样-std=c17 -pedantic-errors?


为什么 gcc 即使在严格模式下也选择不合规?

由于所提出的问题是针对开发人员的动机,因此我们作为第三方必须继续了解的唯一信息来自公共开发工件,例如 GCC bugzilla、存储库提交消息和实际代码。正如评论中指出的那样,这个问题在与更改相关的 Bugzilla 评论线程.

Bugzilla 的讨论似乎表明开发人员考虑了该领域的标准要求,尽管方式有些敷衍。具体见评论9 and 10。他们提出了语言规范第 6.6/10 段:

实现可以接受其他形式的常量表达式。

他们没有对此进行任何特别的审查,我阅读这些评论更多的是为了寻求更改的理由,而不是对 GCC 一致性考虑因素的深思熟虑的调查。

因此,他们做出更改是因为他们想要实现功能请求,并且他们在标准语言中找到了足够的(对他们来说)合理性,认为更改的行为与语言约束一致,因此不需要诊断。


还有一个隐含的问题是,最近 GCC 默默接受所提交的声明表格实际上是否违反了合格处理者诊断约束违规的义务。

尽管可以将 6.6/10 解释为允许实现接受它们选择的任何符合任何类型常量表达式要求的表达式,但这似乎令人担忧。给定的代码片段是否满足语言的约束不应该依赖于实现。如果接受以下任一解释点,都将解决该问题:

  • 6.6/10 应被解释为表达一般规则的特定情况,即一致的实现可以接受不一致的代码,而不意味着这样做使处理器有权将代码视为一致。

  • 6.6/10 应被解释为允许处理器将比前面段落中描述的更多表达式解释为“常量表达式”,但这与这些段落中定义的特定类型常量表达式的定义无关(“整数常量表达式”) ”和“算术常数表达式”)。

这些并不是相互排斥的。我赞成后者,正如我之前写的,我也倾向于前者。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 const 限定变量被接受为 gcc 的初始值设定项? 的相关文章

随机推荐