C++中的一个类型转换

最近在看C++ Primer这本书,第二章讲到类型转换时有一段代码,先贴上来:
#include <iostream>
int main()
{
unsigned u = 10;
int i = -42;
std::cout << i+i << std::endl;
std::cout << u+i << std::endl;
return 0;
}

不知道大家口算的结果是什么样的,下面是我的编译器的输出结果:


对于这个结果,如果大家没感到惊讶,好吧我承认你是大神,对于弱者我来说百思不得姐啊第二个结果,怎么就得到那么大的数了呢?

一番恶搞之下终于算是弄明白了:

如果表达式里既有带符号类型又有无符号类型,当带符号类型为负时可能出现异常结果,因为C++带符号数会自动转换成无符号数,拿

上面的第二个表达式来说,进行运算时,首先-42会被转换为无符号数。把负数转换成无符号数类似于直接给无符号数赋一个负值,结果

等于这个负数加上无符号数的模。

其实这个结果是根据实现的不同而不同的,就是说,我的机子 int 是32位,所以输出是4294967264。下面是内部原理:

首先,无符号数用二进制表示时无符号位!

42在计算机中的存储(32位int):00000000000000000000000000101010


那么-42就是对它求补而得:            11111111111111111111111111010110

好,再加上10,就是                    +  00000000000000000000000000001010

                                                      -------------------------------------------------------------------

                                                        11111111111111111111111111100000

得到的是多少呢? Result = 2^32 - 11111(B)  - 1 = 2^32 - 1 - 31 = 4294967264

自此,问题得到解答!

所以最后想说,在含有无符号类型的表达式里,一定要小心!

无符号数不会小于0这一事实也影响着循环的写法。例如,我们要通过控制变量低贱的方式把从10到0的数字降序输出。这个循环可以这样写:

for(int i = 10; i >= 0; --i)
std::cout << i << std::endl;

可能你觉得反正也不打算输出负数,可以用无符号数来重写这个循环:
for(unsigned i = 10; i >= 0; --i)
std::cout << i << std::endl;

我们来看当i = 0时发生了什么,这次迭代输出0, 然后继续执行for语句里的表达式,--i从i当中减去1,得到的-1并不满足无符号数的要求,此时

像所有表示范围之外的其他数字一样,-1被自动转换为一个合法的无符号数。假设int 类型占32位,则当i=0时,--i的结果是4294967295!!!

一种解决方法是用while循环:

unsigned u = 11;
while(u > 0)
{
--u;
std::cout << u << endl;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值