C语言中的位移运算

位移运算

1.左移

//C左移表达式
x<<k;

  对于一个n位的操作数x,x<<k操作会生成一个值:x向左移动k位,丢弃最高的k位,并在右端补k个0。位移量应该是一个0~n-1之间的值。
  位移运算是从左至右可结合的,所以x<<j<<k等价于(x<<j)<<k。

2.右移

//C右移表达式
x>>k;

  一般而言,机器支持两种形式的右移:逻辑右移和算术右移。逻辑右移在左端补k个0;算术右移是在左端补k个最高有效位。

3.一个例子

Tables Cool
参数x[01100011]  [10010101]
x << 4[00110000]  [01010000]
x >> 4 (逻辑右移)[00000110]  [00001001]
x >> 4 (算术右移)[11110110]  [11111001]


  C语言并没有明确定义应该使用哪种类型的右移。

  • 对于无符号数据(unsigned声明的整形对象),右移必须是逻辑的;
  • 对于有符号数据(默认的声明的整型对象),算术的或者逻辑的右移都可以。然而实际上,几乎所有的编译器/机器组合都对有符号数据使用算术右移,且许多程序员也都假设机器会使用这种右移。

  另一方面,Java对于如何进行右移有明确的定义。表达式x>>k会将x算术右移k个位置,而x>>>k会对x做逻辑右移。

位移操作的注意事项

1.位移k位,k很大

问题:对于一个由w位组成的数据类型,如果要移动k(k>>w)位会得到什么结果呢?
  例如在一个32位的机器上计算下面的表达式会得到什么结果:

int      lval = 0xFEDCBA98 << 32;
int      aval = 0xFEDCBA98 >> 46;
unsigned uval = 0xFEDCBA98 << 40;

  C 语言标准很小心地规避了说明在这种情况下该如何做。在许多机器上,当移动一个w位的值,移位指令只考虑位移量的低 log2w 位,因此实际上位移量就是通过计算k mod w得到的。在一台32位的机器上,上面三个位移运算分别是移动0、4和8位,得到结果:

lval 0xFEDCBA98
aval 0xFFEDCBA9
uval 0x00FEDCBA

  不过这种行为对于C程序来说是没有保障的,所以位移数量应该保持小于字长。

2.与位移有关的操作符优先级问题

1<<2+3<<4

  在C语言中,加法(和减法)的优先级比位移运算要高,然后按照从左至右结合性规则,上述表达式应该这样解释:

(1<<(2+3))<<4

参考资料

《深入理解计算机系统》 第2章 信息的表示和处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值