整型提升 - 步骤是什么

8
这段代码会打印出B2。
short a=-5;
unsigned short b=-5u;
if(a==b)
    printf("A1");
else
    printf("B2");

我读过整数提升的相关资料,但在这个例子中它仍然不太清楚,有人能详细地解释编译器在扩展/截断值时遵循的步骤吗?


你使用的编译器是哪个? - user195488
这个链接可能会很有用:http://en.cppreference.com/w/cpp/language/implicit_cast。 - juanchopanza
整数提升只发生在 a==b 表达式中,这就是你所问的全部内容吗? - Carl Norum
1
我不确定你期望的是什么,但它永远不会相等,因为 unsigned short b = -5u 会被转换为 65531 - Rapptz
1
可能是重复的问题:无符号整数在if语句比较中变为有符号整数? - Bo Persson
显示剩余2条评论
3个回答

11

让我们来看一下你的代码:

short a = -5;

a = -5,适合short类型。到目前为止很容易。

unsigned short b = -5u;

-5u表示将一元运算符-应用于常量5u。5u是(unsigned int)5,一元运算符-不进行提升,因此得到的结果为4294967291,即2^32-5。(更新:我在原始答案中有点错误;请参见测试脚本,显示此版本是正确的:http://codepad.org/hjooaQFW
现在,当将其放入b中时,它被截断为无符号短整型(通常为2个字节),因此b = 65531,即2^16-5。
if( a == b )

在这一行中,a和b都被提升为int类型,以便正确比较。如果它们被提升为short类型,b可能会出现回绕。如果它们被提升为无符号short类型,a可能会出现回绕。
所以这就像是说if( (int) a == (int) b )。而a = -5,所以(int) a = -5,b = 65531,所以(int) b = 65531,因为int类型比short类型大。

3
“Um,‘-5u’是完全合理的。它对整数常量‘5u’应用了‘-’。” - Pete Becker
你提到了我感兴趣的一点:在短变量'a'中存储-5之前,它的常量值被视为整数,对吗?我对这一点非常感兴趣。 - Johnny Pauling
@JohnnyPauling:在赋值之前,-5被转换为有符号整数。然后它被截断为short,但在这种情况下没问题。 - teppic
一元运算符“-”不会导致“5u”的任何转换。它仍然是一个“unsigned int”。对其应用“-”将导致“UINT_MAX - 4”,然后将其转换为“unsigned short”。 - Daniel Fischer
1
@EricPostpischil 我在回应 Dave 的话:“一元运算符 - 将把这个值(我猜是一个 long 类型)提升为 -5。” - Daniel Fischer
显示剩余3条评论

2
a == b

在上述表达式中,ab都被提升为int
unsigned short b=-5u;

在这个声明中,-5U 通过整数转换的方式转换为 unsigned short(C99,6.3.1.3p2适用于此处),并变成一个大值。
引用如下:

(C99, 6.3.1.3p2) "否则,如果新类型是无符号的,则通过反复添加或减去可以在新类型中表示的最大值加一,直到该值在新类型的范围内为止进行转换。"

然后,b 的值为 (unsigned short) ((unsigned int) USHRT_MAX + 1 -5),如果 USHRT_MAX(unsigned short) 65535,那么它就是 (unsigned short) 65531
所以你得到的是: (short) -5 == (unsigned short) 65531 在将操作数提升为整数后,它等同于: -5 == 65531 这相当于 0

关于“在二进制补码系统中”,无论有符号整数的表示方式如何,都是这样的,因为圣洁的标准要求它是二进制的,并且因为5远小于所需范围的最小值,而且标准要求无符号算术是模2^n,其中n是表示位数。因此,对于例如32位unsigned和16位unsigned short,表达式-5u本身产生的值为2^32-5,然后该值对2^16取模必然是2^16-5,同样,无论有符号整数的表示方式如何。 - Cheers and hth. - Alf
@Cheersandhth.-Alf同意,我在你的评论之前删除了这个句子。我最初选择从“二进制补码系统”开始是因为我想添加关于(无)表示更改的信息。 - ouah

1

short 转换为 unsigned short 是一种转换(因此具有转换等级)

short 转换为 int 是一种提升(因此具有提升等级)

由于等级的原因,提升优先于转换。提升发生在算术和其他操作期间。转换仅在将一个整数类型存储在另一个整数类型中时发生。算术运算可以导致转换和提升,以便强制将类型合并。另一个例子:

unsigned int u = 2; 
int i = 2; 
u + i;

i被转换(而不是提升)为unsigned

由于被转换为unsigned,您的值被转换为一个更大的值,因为它发生了包装。然后,它们被提升为int。因此,a != b就是这个原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接