如何解决为什么在 gcc 上接受 const 限定变量作为初始值设定项?
在最新版本的 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):
整数常量以数字开头,但没有句点或指数部分。它可能有一个指定其基础的前缀和一个指定其类型的后缀。
因此 const int
变量不是整数常量,也不是整数常量表达式。因此不是有效的初始化程序。这之前已经讨论过(例如 here),我认为已经确定这是不合格的。但是,我的问题是:
为什么 gcc 即使在严格模式下也选择不合规?
clang 显然一直不合规,但 gcc 从 7.3 版的合规变成了 8.0 及以上版本的不合规。即使在没有 -pedantic-errors
的默认模式下,gcc 7.3 及更早版本也会给出“错误:初始化元素不是常量”。
似乎已经对这条消息做出了某种主动的、有意识的决定。为什么在 gcc 中完全删除它,为什么在严格模式 -std=c17 -pedantic-errors
下编译时不保留它?
解决方法
为什么 gcc 即使在严格模式下也选择不合规?
由于所提出的问题是针对开发人员的动机,我们作为第三方必须继续提供的唯一信息来自公共开发工件,例如 GCC bugzilla、存储库提交消息和实际代码。正如评论中指出的那样,该问题在 the Bugzilla comment thread associated with the change 中进行了讨论。
Bugzilla 的讨论似乎表明,开发人员考虑了该领域的标准要求,尽管有些敷衍。请特别查看注释 9 和 10。他们提出了语言规范的第 6.6/10 段:
一个实现可以接受其他形式的常量表达式。
他们没有对此进行任何特别的审查,我阅读这些评论更多是为了寻求更改的理由,而不是对 GCC 一致性考虑的深思熟虑。
因此,他们进行更改是因为他们想要实现功能请求,并且他们在标准语言中找到了足够的(对他们而言)理由来考虑更改的行为与语言约束一致,因此不需要诊断.
还有一个隐含的问题,即最近 GCC 对所提供的声明表格的沉默接受是否实际上违反了合规处理者诊断违反约束的义务。
尽管可以将 6.6/10 解释为允许实现接受他们选择的任何表达式,以符合任何类型的常量表达式的要求,但这似乎令人担忧。一段给定的代码是否满足语言的约束不应该依赖于实现。如果接受这些解释点中的任何一个,都可以解决该问题:
-
6.6/10 应被解释为表达了通用规则的特定情况,即符合要求的实现可以接受不符合要求的代码,但不暗示这样做会使处理器有权将代码视为符合要求。
-
6.6/10 应该被解释为允许处理器将更多的表达式解释为“常量表达式”,而不是在前面的段落中描述的那些,但这与那些中定义的特定类型的常量表达式的定义无关。段落(“整数常量表达式”和“算术常量表达式”)。
这些并不相互排斥。我赞成后者,as I have written previously,而且我也倾向于前者。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。