示例
int main()
{
const int i = 1.0; // Notice I am assigning a double to an int here
char a[i];
}
问题
用 g++ -O0 -Wall -pedantic -ansi -std=c++11
编译上面的代码没有错误(除了未使用的变量)。但是,如果我删除 -std=c++11
,我会收到以下警告:
warning: ISO C++ forbids variable length array
根据 this SO question ,我相信在 C++03 中,代码是无效的。但是,有人可以解释一下规则在 C++11 中发生了什么变化吗?
(这个问题是我回答的a previous question的结果。)
最佳答案
数组边界必须是整数常量表达式,参见 8.3.4 [dcl.array]/1(C++03 和 C++11 中的相同措辞):
If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.
在 C++03 中,整型常量表达式不能由浮点字面量初始化,除非转换为整型,参见 5.19 [expr.const]/1 的最后一句:
An integral constant-expression can involve only literals (2.13), enumerators,
const
variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, andsizeof
expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types.
这意味着在 C++03 中 i
不是整数常量表达式,因此不能用作数组绑定(bind)。
GCC 和 Clang 允许将可变长度数组作为 C++03 的扩展,因此它使用非常量绑定(bind)进行编译,但您会收到一个带有 -pedantic
的警告。更改常量的初始值设定项以将其转换为整数类型使 i
成为有效的整数常量表达式:
const int i = (int) 1.0;
有了这个改变,数组不再是可变长度的,即使使用 -pedantic
也没有警告。
在 C++11 5.19 [expr.const]/3 中说:
A literal constant expression is a prvalue core constant expression of literal type, but not pointer type. An integral constant expression is a literal constant expression of integral or unscoped enumeration type.
前面(相当长)的段落描述了核心常量表达式的规则,但基本上在 C++11 中,双初始化器不会阻止 i
成为核心常量表达式,即使没有强制转换,所以它是一个整数常量表达式,因此是一个有效的数组边界,所以没有警告。
关于c++ - 使用浮点文字初始化 const int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10925459/