【运算符的几个小坑点】unsigned int32 x = -1 >> 2 = 4294967295?
- 今天闲谈时候的一点复习、发现和研究。
为了解决这个问题,我们需要一些前置知识点。
第一步:原码,反码,补码
- 在现在大部分计算机,我们使用
补码存储数值。
如果是有符号值signed,最左边的一位符号位,其他的都存储数值。
符号位,我们规定0表示正数,1表示负数 - 原码
即第一位是符号位,后面用二进制表示数,不足用前导0补足。 - 我们规定正数的补码就是原码本身
如果是8位情况下:
比如3,原码和补码都是0000 0011 - 我们规定反码就是原码每一位取反
比如-0的反码就是1111 1111 - 然后我们发现,如果用反码表示数,那么
+0和-0表示不一致了!
这个时候我们用到 补码:就是反码加一。
比如-0的补码就是1111 1111 + 1 = 0000 0000 (第一个1上溢了)
比如-2的原码是1000 0010反码是0111 1101补码是0111 1110
第二步:无符号数
- unsigned 无符号数,自然本来第一个符号位的 bit 就改为存储值了。
于是unsigned int4 (-1) = 1111(b) = 15
无符号数不是符号位永远是0!
第三步:无符号数情况下的位移运算符
- 如果
unsigned int32 x = -1
那么输出的x = 1111 1111 1111 1111 1111 1111 1111 1111 = 4294967295
我们已经是知道了。
如果我再求x = x >> 2,是多少呢?很明显,右移两位,会导致左边两位空出来,就变成:
x = 0011 1111 1111 1111 1111 1111 1111 1111 = 1073741823
第四步:有符号数情况下的位移运算符
- 坑点在这里:题目要求的
-1 >> 2并不等于-(unsigned int)1 >> 2请注意!
所以这里的位移运算符是针对有符号数,也就是默认的(int)-1的!
对于有符号数的左移运算符,右侧补充0
对于有符号数的右移运算符,左侧补充符号位 - 举例子吧。下面为有符号数。
3 = 0011(b)那么3 << 1 = 0110 = 6
-1 = 1111(b)那么-1 << 1 = 1110 = -2
可以看出,左移在没有进位到符号位的前提下,都是等于原来的数乘以 2 k 2^k2k
3 = 0011(b)那么3 >> 1 = 0001 = 1
-1 = 1111(b)那么-1 >> 1 = 1111 = -1
-3 = 1101(b)那么-3 >> 1 = 1110 = -2
可以看出,正数右移,左侧补 0 00 ,相当于原来的数除以2向下取整。
负数右移,左侧补 1 11。注意到,此时仍然相当于原来的数除以2向下取整。
同理 − 1 > > k = − 1 -1 >> k = -1−1>>k=−1 只要 k kk 是非负数都是成立的。
第五步:题目的解答
unsigned int32 x = -1 >> 2 = (int)-1 = 1111 1111 1111 1111 1111 1111 1111 1111(b) = 4294967295- 如果我们强制类型转化一下,答案就截然不同了
unsigned int32 x = (unsigned)-1 >> 2 = 0011 1111 1111 1111 1111 1111 1111 1111(b) = 1073741823
这个等价于:
unsigned int32 x = -1;x >>= 2;
再提一嘴
- 如果出现
x << -5其实就相当于x >> 5
如果出现y >> -6其实就相当于y << 6
上述所有数值都在Code Blocks中测试过一遍。
版权声明:本文为weixin_45775438原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。