1、案例现象:
不同类型值相加结构与理想值不一致。
int main()
{
int i = -20;
unsigned int j = 10;
cout << i + j << endl;
system("pause");
return 0;
}
输出结果:4 294 967 286
2^32-10=4 294 967 296-10=4 294 967 286
2、原因:
两个兼容的不同类型的值相加,哪个数能表示更大的数(正数)就转为那个数的类型。例如short
+long
,就要转为long
;unsigned
+signed
,就要转为unsigned
。
2.1、案例解释
在32位机上unsigned int
最大可表示2^32 - 1
; int
最大可表示2^31-1
;
这样int
就转为了unsigned int
,由于i<0
,即i
的最高位符号位是1,转为unsigned int
后最高位不再是符号位,而是一个正数的有效位,于是两者相加就会是一个很大的正数了。
计算详细过程
1、int -20在32位计算机中的存储形式为:1111 1111 1111 1111 1111 1111 1110 1100 第一位1为符号位,表示负数
2、unsigned 10在32位计算机中的存储形式为:0000 0000 0000 0000 0000 0000 0000 1010
3、unsigned+int 后结果转为unsigned存储,故int -20转化为unsigned int,由于符号位为1,转为unsigned int 后最高位不再是符号位,而是一个最高正的位数,两者相加为1111 1111 1111 1111 1111 1111 1111 0110 即为4 294 967 286。
3、为什么“哪个能表示更大的数就转为哪个类型”?
因为计算机(注意,是计算机,不是编译器,也不是操作系统)总是希望能尽量大的囊括结果,防止溢出产生错误(尽管有人会说向下溢出怎么办,但别忘了,负数加减换成补码也成了正数的加运算)。
总结:
1、两个兼容的不同类型的值相加,哪个数能表示更大的数(正数)就转为那个数的类型。例如short
+long
,就要转为long
;unsigned
+signed
,就要转为unsigned
。
参考资料:
1、本文为转载后重新编排,原文链接:【该文讲了原理】unsigned与int相加的问题
2、【该文讲了现象】浅谈unsigned int与int相加的问题