C++ 和 C 标准中的哪些规则使得从其他静态对象初始化静态对象在 C++ 中有效,但在 C 中无效

Muh*_*aby 0 c c++ initialization language-lawyer storage-duration

为什么下面的代码编译为 C++ 时没有任何抱怨,但 C 编译器却抱怨初始化器不是编译时常量?

int x = 2;
int y = 1;
    
int a[2] = {x, y};

#include <stdio.h>

int main()
{
    printf("Hello world\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*cow 5

来自 C11 标准(6.7.9 初始化)

\n
\n

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

\n
\n

在 C 中这些声明

\n
int x = 2;\nint y = 1;\n
Run Code Online (Sandbox Code Playgroud)\n

不提供常量表达式。就算你会写

\n
const int x = 2;\nconst int y = 1;\n
Run Code Online (Sandbox Code Playgroud)\n

然后,它们再次不提供允许用作具有静态存储持续时间的对象的初始值设定项的编译时常量表达式。

\n

来自 C11 标准(6.6 常量表达式)

\n
\n

7 初始值设定项中的常量表达式允许有更多的自由度。\n这样的常量表达式应为以下之一,或计算为以下之一:\n

\n

\xe2\x80\x94 算术常量表达式,

\n

\xe2\x80\x94 空指针常量,

\n

\xe2\x80\x94 地址常量,或

\n

\xe2\x80\x94 完整对象类型的地址常量加上或减去整数常量表达式。

\n
\n

\n
\n

8算术常量表达式应具有算术类型,并且只能具有整型常量、浮点常量、枚举常量、字符常量和sizeof表达式的操作数。算术常量表达式中的转换运算符只能将算术类型转换为算术类型,除非作为结果为整型常量的 sizeof 运算符的操作数的一部分

\n
\n

如果您的编译器支持 C23 标准,那么您可以编写

\n
constexpr int x = 2;\nconstexpr int y = 1;\n\nint a[2] = { x, y };\n
Run Code Online (Sandbox Code Playgroud)\n

在 C23 中,标识符xy被称为命名常量,并且命名常量可以用作具有静态存储持续时间的对象的初始值设定项。

\n

在 C++ 中,具有静态存储持续时间的对象的初始化

\n
int x = 2;\nint y = 1;\n\nint a[2] = { x, y };\n
Run Code Online (Sandbox Code Playgroud)\n

称为动态初始化并在运行时发生。

\n