关于c语言中负数位移位操作的漫谈

最近有个朋友在程序中使用了对16进制数做负数移位(编译器是gcc),本人最次产生好奇,所以研究了一些。

对一个数做负数位移位的操作是不规范的,但是是可行的。
具体例子:
char tmp = 0x10;
tmp = tmp << -1;
大家猜猜结果是什么,有人猜是tmp左移-1位不就是右移1位吗?结果是0x01?
很遗憾,电脑和人脑是不一样的。结果是0
为什么呢?为了找出原因,本人进行了一些小小的测试,并做出了有依据的结果。

由于知道+0和-0的区别,所以,我首先将tmp << -128(-128就是-0),和猜想的一样,结果是0x10
而-128的二进制是 1000 000b
继续,将tmp << -127,结果是0x20,左移了1位
-127的二进制是 1000 0001b
迫不及待,尝试 tmp << -126,结果是0x40,左移了2位
-126的二进制是 1000 0010b
这时,大家应该和我一样,看出了端倪,但是先不要说出来,先看看他们以同样的值向右移:
首先将tmp >> -128(-128就是-0),结果是0x10
而-128的二进制是 1000 000b
继续,将tmp >> -127,结果是0x08,右移了1位
-127的二进制是 1000 0001b
迫不及待,尝试 tmp >> -126,结果是0x04,右移了2位
-126的二进制是 1000 0010b

这时,大家可以大胆的的猜测了,移位操作中若移动的是一个负数,那么移动的位数以这个负数的二进制形式的低七位决定。
若还有猜疑,继续测试:
tmp << -255 结果为0x20,-255的二进制为0x1 0000 0001b
tmp << -511 结果为0x20, -511的二进制为0x10 0000 0001b
tmp << -1023 结果为0x20,-1023的二进制为0x100 0000 0001b

现在大家可以肯定的说: 移位操作中若移动的是一个负数,那么移动的位数以这个负数二进制形式的低七位决定。(现在的longlong型长度貌似最大也只有到64位,若要达到128位,这个编译器就要修改了。)

在写完本文后,我在工作中不小心发现了不妥。以上的结果只是仅仅代表了有符号char型的移位规则。所以,以上的结论需要进一步的进行拓展。
下面是拓展后的结论:
当一个数为有符号数时,设这个有符号数的二进制位数为k(比如int型在32位系统中,它的二进制位数为32),那么这个数向左或向右移动n位时,这个数只移动这个n数的二进制形式下低k-1位所指代的那个正数位。
当一个数为无符号数时, 设这个有符号数的二进制位数为k(比如int型在32位系统中,它的二进制位数为32),那么这个数向左或向右移动n位时,这个数只移动这个n数的二进制形式下低k位所指代的那个正数位。

由于本人水平有限,如有错误,请指正。本人不胜感激。




  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值