索引字符串文字是否是初始化程序常量表达式?

时间:2019-06-15 15:38:31

标签: c language-lawyer c11 constant-expression c17

以下代码尝试在两个不同的常量上下文中对字符串文字使用数组索引:

static char x = "abcx"[3];

_Static_assert ("abcx"[3] == 'x', "...");

根据Compiler Explorer的判断,工具供应商之间存在明确的共识,即不允许在第二种情况下这样做,因为第二种情况明确要求使用整数常量表达式。但是,它们似乎在第一个上下文方面有所不同,第一个上下文只是初始化程序中使用的算术常量表达式。 GCC和Clang是允许这样做的实现。

这本身并不有趣,因为在paragraph 10 of 6.6中,C11 / C18确实表示“实现可以接受其他形式的常量表达式”。但是,在这种情况下它之所以突出,是因为:

  • GCC和Clang都用-pedantic静默接受此命令(是的,编译器签发并不意味着代码符合要求)。构建代码是有道理的,因为其含义很简单,但是如果他们认为这不符合要求,我会发出警告,并且他们可以识别(他们认为)它是否符合要求,因为...

  • 这两个编译器的行为最近都已更改 -Clang一直在此之前引发错误,直到3.8,而GCC之前一直在引发错误,直到8.0。这些版本分别于2016年和2018年发布。这表明更改是有意的,但我还没有找到详细介绍这一级别的任何编译器的发行说明。

行为改变的时机使其看起来与C18有关,但6.6的措词似乎没有改变。对整型常量表达式的限制仍然严格(如第二行继续显示错误),第9段的措词似乎与C11中的相同,尤其是继续说:“不能通过使用这些运算符来访问对象的值”(wrt []和朋友)。

通过任何对标准的阅读,第一个上下文是否是有效的初始化程序常量,而不包括第10段?我在哪里可能找到GCC / Clang变更的理由?

1 个答案:

答案 0 :(得分:2)

6.6常量表达式,¶8:

  

算术常数表达式应具有算术类型,并且只能具有整数常数浮点常数枚举常数字符常量表达式的大小(其结果是整数常量)和 _Alignof表达式。算术常数表达式中的强制转换运算符只能将算术类型转换为算术类型,除非作为操作数的一部分转换为sizeof或_Alignof运算符。

字符串文字不是上面6种操作数类型中的任何一种,因此该表达式不是算术常数表达式,除非它被接受为扩展名。