为什么下面的表达式表征了一个缩小的转换?

时间:2014-01-20 19:04:34

标签: c++ c++11 language-lawyer narrowing

此表达式可在标准(N3797)§8.5.4/ 7中的示例中找到

unsigned int ui1 = {-1}; // error: narrows

鉴于§8.5.4/ 7及其第4个要点:

  

缩小转化是隐式转换:

     
      
  • 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,   除非源是一个常量表达式,其值后面   积分促销将适合目标类型。
  •   

我想说这里没有缩小,因为-1是一个常量表达式,其积分提升后的值适合无符号整数。

另见§4.5/ 1关于整体推广

  

除bool,char16_t,char32_t或之外的整数类型的prvalue   wchar_t,其整数转换等级(4.13)小于等级   如果int可以表示all,则int可以转换为int类型的prvalue   源类型的值;否则,源prvalue可以   转换为unsigned int类型的prvalue。

从4.13开始,我们得到-1(一个int)的等级等于unsigned int的等级,因此它可以转换为unsigned int。

修改

不幸的是Jerry Coffin从这个帖子中删除了他的答案。我相信他是在正确的轨道上,如果我们接受§8.5.4/ 7中第4个要点的当前读数是错误的,在标准中change之后。

3 个答案:

答案 0 :(得分:7)

intunsigned int没有完整的促销活动,因此仍然不合格。

这将是积分转换

答案 1 :(得分:1)

  

缩小是从整数类型到整数类型的隐式转换,它不能代表原始类型的所有值

从整数类型int到整数类型unsigned int的转换当然不能代表原始类型的所有值 - 标准在这里是非常明确的。如果你确实需要它,你可以做到

 unsigned int ui1 = {-1u};

这样做没有任何错误/警告,因为1uunsigned int类型的文字,然后被否定。这在标准状态中明确定义为 [expr.unary.op]

  

无符号数量的负数是通过从2 n 中减去其值来计算的,其中n是提升操作数中的位数。

然而,

-1在否定之前和之后是int,因此它变为缩小的转换。 There are no negative literals;有关详细信息,请参阅this answer

促销是非正式地将相同的值复制到更大的空间中,因此不应混淆,因为signedunsigned的大小相等。即使您尝试将其转换为某种类型的较大尺寸,请说unsigned long long它仍然是一个缩小的转换,因为它不能真正代表负数。

答案 2 :(得分:1)

标准措辞的改变旨在确认将负值转换为无符号类型的理解并且始终是一个缩小的转换。

非正式地,-1不能在任何无符号类型的范围内表示,并且表示它的位模式如果存储在unsigned int中则不表示相同的值。因此,这是一个缩小的转换,不涉及促销/扩大。

这是关于阅读标准的精致艺术。像往常一样,编译器最了解。