使用浮点文字初始化const int

Jes*_*ood 8 c++ constants c++11

int main()
{
    const int i = 1.0; // Notice I am assigning a double to an int here
    char a[i];
}
Run Code Online (Sandbox Code Playgroud)

编译上面的代码g++ -O0 -Wall -pedantic -ansi -std=c++11没有给出错误(除了未使用的变量).但是,如果我删除-std=c++11,我会收到以下警告:

警告:ISO C++禁止变长数组

根据这个SO问题,我相信在C++ 03中,代码无效.但是,有人可以解释一下规则在C++ 11中的变化吗?

(这个问题是我回答的上一个问题的结果.)

Jon*_*ely 7

数组绑定必须是整数常量表达式,参见8.3.4 [dcl.array]/1(C++ 03和C++ 11中的相同措辞):

如果存在常量表达式(5.19),则它应为整数常量表达式,其值应大于零.

在C++ 03中,除非转换为整数类型,否则不能通过浮动文字初始化整数常量表达式,请参见5.19 [expr.const]/1的最后一句:

一个积分常数表达式可以只涉及文字(2.13),统计员,const变量或常量表达式(8.5),积分或枚举类型的非类型模板参数,并初始化积分或枚举类型的静态数据成员sizeof表达式.浮动文字(2.13.3)只有在转换为整数或枚举类型时才会出现.

这意味着在C++ 03 i中不是一个整型常量表达式,因此不能用作数组绑定.

GCC和Clang允许可变长度数组作为C++ 03的扩展,因此它使用非常量绑定进行编译,但是会收到警告-pedantic.更改常量的初始化程序以将其强制转换为整数类型会i生成有效的整数常量表达式:

const int i = (int) 1.0;
Run Code Online (Sandbox Code Playgroud)

通过该更改,数组不再是可变长度,即使使用也没有警告-pedantic.

在C++ 11 5.19 [expr.const]/3中说:

常量表达式是文本类型的prvalue核心常量表达式,但是没有指针类型.一个积分常量表达式是整体的或无作用域枚举类型的字面常量表达式.

前面(相当冗长的)段落描述了核心常量表达式的规则,但基本上在C++ 11中,双初始化器不会阻止i成为核心常量表达式,即使没有强制转换,因此它是一个整型常量表达式,因此是有效的数组绑定,所以没有警告.