首页 > 类型转换问题

类型转换问题

unsigned u=10;
int i=-42;
cout<<i+i<<endl;
cout<<u+i<<endl;

不理解,
结果居然是
-84 4294967264

2的32次方是4294967296.


unsigned与int的本质区别是,unsigned用原码表示0~2^32-1,int用补码表示-2^31~2^31-1
int与unsigned相加时,是作为unsigned处理的,返回结果也作为unsigned处理
int i=-42是用补码表示的,把它当做原码的话就是2^32-42
跟10相加,结果是2^32-32=4294967264


1、i+i是int类型相加,无类型转换,故为-42+(-42)=-84
2、u+i是unsigned int和int类型相加,隐式转换成unsigned int,(int) i =-42 = (unsigned int) i = 2^32 - 42 = 4294967254,则u+i=4294967254+10=4294967264


cout << i + i << endl;  // -84

以32位机器为例,int能表示的最大值为2^32 - 1,最小值为-2^32。超过这个区间的int会溢出。这里,i=-42,显然不会溢出。两个int相加,结果还是int,所以得到-84是理所当然。

cout << u + i << endl;  //4294967264

这里是unsigned int和int相加,两种不同的类型相加,编译器会做隐式类型转换。怎样转换?把有符号的转为无符号的!所以,这行代码相当于:

cout << u + (unsigned) i << endl;

关键问题是,怎样把int转为unsigned int?

计算机用补码表示负数,以整形i=-42为例,它在32位计算机中的补码表示为:11111111111111111111111111010110(如果按照16进制,则表示为:FFFFFFD6)

所谓某个变量是int还是unsigned int,在计算机看来都是一回事。关键在于编译器怎样“看待”这个变量。现在编译器不把这个FFFFFFD6当int看了,而是要把它当unsigned int看待。于是,FFFFFFD6的含义就变成了:

FFFFFFD6 = 2^31 + 2^30 + ... + 2^7 + 2^6 + 2^4 + 2^2 + 2^1 = 4294967254

也就是说,(int)-42与(unsigned int)4294967254其实是一回事,只不过编译器对它们的解释不同而已。

结果已经很明了:4294967254 + 10 = 4294967264,这就是你得到的输出!


C++支持类型扩展,也就是说当一个能表示大范围的类型和一个能表示小范围类型做运算时,小范围类型会自动强转为大范围类型,在C++的规定中,unsigned int 比int的范围大,所以做运算u+i时,i被强制转换为unsigned int类型,-42被强转为unsigned类型后为4294967254u,加上10u就是4294967264u

【热门文章】
【热门文章】