为什么 GCC/Clang 会接受 const 限定对象作为具有静态存储持续时间的对象的初始值设定项?

iDi*_*ong 1 c static constants

据我所知,ISO C 标准对 C11 6.7.9 中具有静态存储持续时间的对象的初始值设定项很严格

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

但是 GCC/Clang 都接受了以下代码:

const int i = 3; // const here should not make i a constant expression
static int j = i;
Run Code Online (Sandbox Code Playgroud)

即使有-Wall -Wextra -Werror -pedantic-errors,上面的编译器也没有给我任何抱怨。

但是,这些编译器确实意识到这i不是一个常量表达式。例如,Clang 给了我:

错误:静态数组的大小必须是整数常量表达式

对于以下代码:

const size_t sz = 3;
static int a[sz];
Run Code Online (Sandbox Code Playgroud)

我在这里有什么问题吗?

Sto*_*ica 5

您没有遗漏任何东西,它确实是一个不符合标准的 C 程序,并且是编译器方面的一种不符合标准的行为。这很可能是由于 GCC 和 Clang 也是 C++ 的编译器套件造成的。在 C++ 中i是一个有效的初始化器j

然而值得注意的是,虽然编译器可以自行决定翻译不符合标准的 C 程序,但他们仍然必须根据 C11 5.1.1.3 p1 发布关于不符合标准的诊断:

如果预处理翻译单元或翻译单元违反任何语法规则或约束,即使该行为也明确指定为未定义或实现,则一致实现应产生至少一个诊断消息(以实现定义的方式标识)定义。在其他情况下不需要产生诊断消息。

即使我们接受行为作为扩展,事实上 GCC 和 Clang 不发出诊断是他们双方的一致性错误。