第8.5.4 / 7节中的标准解释了缩小转换的含义:
缩小转化是隐式转化
- 从浮点类型到整数类型,或
- 从long double到double或float,或从double到float,除非source是常量 表达式和转换后的实际值在可以表示的值范围内 (即使它无法准确表示),或
- 从整数类型或未范围的枚举类型到浮点类型,除了源 是一个常量表达式,转换后的实际值将适合目标类型 转换回原始类型时生成原始值,或
- 从整数类型或未范围的枚举类型到不能代表所有的整数类型 原始类型的值,除非源是常量表达式,后面是实际值 转换将适合目标类型,并在转换回时生成原始值 原始类型。
然后在某些列表初始化上下文中禁止这样的转换,给出 示例:
[注意:如上所述,列表初始化中的顶层不允许进行此类转换。 - 结束 注意] [例子:
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
- 结束示例]
示例中说明的所有7个错误都是这样报告的
铿锵3.2 / 3.3与-std=c++11
,例如
error: non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list [-Wc++11-narrowing]
gcc 4.7.2 / 4.8.1中没有一个被报告为错误,但在每种情况下 也给出了类似的警告,例如
warning: narrowing conversion of ‘x’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]
(因此gcc似乎知道合规要求,但选择容忍不合规 默认情况下。)
我不明白的是示例:
unsigned int ui1 = {-1}; // error: narrows
作为一个例子。 (与对称的si1
示例相同。)显然
可能作为例子的唯一单词是第四个单词
上面给出的缩小转换定义中的最后一项;但
如果是这样,为什么这个例子不能通过资格逃脱
除了源是常量表达式和后面的实际值
转换将适合目标类型,并在转换回时生成原始值
原始类型?当然-1
有一个整数常量,如果转换为unsigned
并返回,
仍然产生int -1
?
我错过了什么?
答案 0 :(得分:6)
肯定-1是一个整数常量,如果转换为无符号又返回,仍然会产生int -1?
这是错误的。如果您将-1转换为unsigned
,则会获得UINT_MAX
。这很好,因为始终定义转换为无符号类型。但是,UINT_MAX
不适合int
,只有当值适合目标类型时,才能通过标准定义对签名类型的转换。