C ++ 11变量缩小,没有GCC编译器警告

时间:2011-11-24 00:54:51

标签: c++ c++11

缩小的概念似乎很简单。但是,有人可以解释为什么下面的一些代码导致“缩小”编译器错误而其他代码没有?

此代码会产生预期的错误:

constexpr int a = 255;
unsigned char b = a;      // OK
unsigned char c = a + 1;  // Error... expected

此代码不会产生错误,但可能没问题:

int d = 256;
unsigned char e = d;  // Maybe OK because 'd' is not constexpr

此代码应生成错误(除非我遗漏了某些内容):

int f = 42.0;  // Maybe OK because no fractional part
int g = 42.1;  // OK... should fail!!
constexpr float h = 42.7;
int i = h;     // OK... should fail???

我正在使用g ++ 4.6.2。我搜索了GCC错误数据库,没有发现任何相关内容。谢谢!

3 个答案:

答案 0 :(得分:9)

老实说,你的样品我看错了。

但是,在许多情况下,编译器似乎接受了“违反”标准转换规则......:

初始化列表(第8.5.4节)

但是我在标准中发现了这个:

对于初始化列表,不允许以下内容(第8.5.4节, 3。下)

int ai[] = { 1, 2.0 }; // error narrowing

6 下,继续提供一般示例列表:

  

[注意:如上所述,列表初始化中顶层不允许进行此类转换。-end   注意]

int x = 999; // x is not a constant expression
const int y = 999;
const int z = 99;
char c1 = x; // OK, though it might narrow (in this case, it does narrow)
char c2{x}; // error: might narrow
char c3{y}; // error: narrows (assuming char is 8 bits)
char c4{z}; // OK: no narrowing needed
unsigned char uc1 = {5}; // OK: no narrowing needed
unsigned char uc2 = {-1}; // error: narrows
unsigned int ui1 = {-1}; // error: narrows
signed int si1 =
{ (unsigned int)-1 }; // error: narrows
int ii = {2.0}; // error: narrows
float f1 { x }; // error: might narrow
float f2 { 7 }; // OK: 7 can be exactly represented as a float
int f(int);
int a[] = { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level

有趣的是,带有--std=c++0x -Wall -pedantic的g ++ 4.6.1只捕获这些违规行为中的一个

    char c3{y}; // warning: overflow in implicit constant conversion [-Woverflow]

外部初始化程序列表......

我认为将浮点数截断为int不会被视为narrowing

这只是一个明确定义的转换,很像

int i = 31;
i /= 4;   // well defined loss of precision...   
i /= 4.0; // equally well-defined conversion from floating point to int

答案 1 :(得分:1)

浮点数可以转换为整数:

  

浮点类型的prvalue可以转换为整数类型的prvalue。转换trun-   凯茨;也就是说,丢弃小数部分。如果截断值不能,则行为未定义   以目的地类型表示。

int f = 42.0;  // Equal to 42, 42 fits into int
int g = 42.1;  // Equal to 42, 42 fits
constexpr float h = 42.7;
int i = h;     // 42

缩小规则仅适用于初始化列表。

unsigned char c = { 2.4 }; // narrowing

warning: narrowing conversion of ‘2.3999999999999999e+0’ from ‘double’ to ‘unsigned char’ inside { } [-Wnarrowing]

答案 2 :(得分:0)

此代码会产生预期的错误:

constexpr int a = 255;
unsigned char b = a;      // OK
unsigned char c = a + 1;  // Error... expected

这会导致缩小误差,因为:
1.(a + 1)产生一个int值 2. rvalue不适合char类型的有效范围

int d = 256;
unsigned char e = d;  // Maybe OK because 'd' is not constexpr

此代码不是缩小的右值。它是从int到unsigned char的隐式转换。