为什么下面的代码编译成C++没有问题,但C编译器却抱怨初始化器不是编译时常量?
int x = 2; int y = 1; int a[2] = {x, y}; #include <stdio.h> int main() { printf("Hello world\n"); return 0; }
wxclj1h51#
从C11标准(6.7.9初始化)4具有静态或线程存储期限的对象的初始化器中的所有表达式都必须是常量表达式或字符串文字。在C中,这些声明
int x = 2; int y = 1;
不提供常量表达式。即使你会写
const int x = 2; const int y = 1;
然后它们也不提供允许用作具有静态存储持续时间的对象的初始化器的编译时常数表达式。.从C11标准(6.6常量表达式)7初始化器中的常量表达式允许有更大的自由度。这样的常量表达式应该是或评估为以下之一:
constexpr int x = 2; constexpr int y = 1; int a[2] = { x, y };
在C23中,标识符x和y被称为 named constants 和 named constants 可以用作具有静态存储持续时间的对象的初始化器。在 C++ 中,对具有静态存储期的对象的一种初始化
x
y
int x = 2; int y = 1; int a[2] = { x, y };
称为动态初始化,并在运行时发生。
a7qyws3x2#
在C中,静态存储持续时间对象(如全局变量a)必须用常量表达式初始化,而x和y不是(在C或C中)。在C中,这样的对象可以用任何表达式初始化,它们也可以作为自动存储持续时间变量初始化。然而,对于全局变量,初始化可能发生在运行时,通常在输入main之前,并且主要以未指定的顺序进行。因此,如果可能的话,通常应该避免使用像这样的非constexpr全局变量,或者需要特别注意以正确的顺序初始化依赖项。C在运行时不做任何动态初始化。
a
main
constexpr
gopyfrb33#
这个表达式:
int a[2] = {x, y};
需要运行时代码来计算x和y的值,并且在C中不允许在函数外部运行代码,但在C中是允许的。下面是C代码:
#include <iostream> class test { private: int a; int b; public: abc() { cin >> a; cin >> b; } }; test x; int main() { return 0; }
文件作用域对象x具有带构造函数的类类型。这意味着必须在调用main之前对其进行初始化,并且初始化需要运行代码,因此这需要一种机制来运行main函数之外的代码。相比之下,C没有在函数之外运行代码的核心需求,所以它从未被引入。因此,C中任何静态对象的初始化都需要在编译时修复初始化器。当C++从C创建时,添加在main之外运行代码的能力成为核心语言运行所必需的。
3条答案
按热度按时间wxclj1h51#
从C11标准(6.7.9初始化)
4具有静态或线程存储期限的对象的初始化器中的所有表达式都必须是常量表达式或字符串文字。
在C中,这些声明
不提供常量表达式。即使你会写
然后它们也不提供允许用作具有静态存储持续时间的对象的初始化器的编译时常数表达式。.
从C11标准(6.6常量表达式)
7初始化器中的常量表达式允许有更大的自由度。这样的常量表达式应该是或评估为以下之一:
和
8 * 算术常量表达式 * 必须具有算术类型,并且只能具有整数常量、浮点常量、枚举常量、字符常量和sizeof表达式的操作数。算术常数表达式中的强制转换运算符只能将算术类型转换为算术类型,除非作为结果为整数常数的sizeof运算符的操作数的一部分。
如果你的编译器支持C23标准,那么你可以写
在C23中,标识符
x
和y
被称为 named constants 和 named constants 可以用作具有静态存储持续时间的对象的初始化器。在 C++ 中,对具有静态存储期的对象的一种初始化
称为动态初始化,并在运行时发生。
a7qyws3x2#
在C中,静态存储持续时间对象(如全局变量
a
)必须用常量表达式初始化,而x
和y
不是(在C或C中)。在C中,这样的对象可以用任何表达式初始化,它们也可以作为自动存储持续时间变量初始化。然而,对于全局变量,初始化可能发生在运行时,通常在输入
main
之前,并且主要以未指定的顺序进行。因此,如果可能的话,通常应该避免使用像这样的非constexpr
全局变量,或者需要特别注意以正确的顺序初始化依赖项。C在运行时不做任何动态初始化。gopyfrb33#
这个表达式:
需要运行时代码来计算
x
和y
的值,并且在C中不允许在函数外部运行代码,但在C中是允许的。下面是C代码:
文件作用域对象
x
具有带构造函数的类类型。这意味着必须在调用main
之前对其进行初始化,并且初始化需要运行代码,因此这需要一种机制来运行main
函数之外的代码。相比之下,C没有在函数之外运行代码的核心需求,所以它从未被引入。因此,C中任何静态对象的初始化都需要在编译时修复初始化器。
当C++从C创建时,添加在
main
之外运行代码的能力成为核心语言运行所必需的。