C语言中的位移运算

来源:互联网 发布:淘宝淘抢购怎么收费 编辑:程序博客网 时间:2024/04/29 14:10

位移运算

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 0xFEDCBA98aval 0xFFEDCBA9uval 0x00FEDCBA

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

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

1<<2+3<<4

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

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

参考资料

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

0 0
原创粉丝点击