Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1131007
  • 博文数量: 254
  • 博客积分: 1242
  • 博客等级: 少尉
  • 技术积分: 1581
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-03 21:49
文章分类

全部博文(254)

文章存档

2017年(16)

2016年(4)

2013年(94)

2012年(140)

分类: C/C++

2012-05-27 11:49:42

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
    


(下面所有的测试为Linux平台,gcc编译器)
  1. #include <stdio.h>
  2. #include <stdlib.h>


  3. int main ()
  4. {
  5.     int a = 0x80000000;
  6.     unsigned int b = 0x80000000;

  7.     printf("a right shift value is 0x%X\n", a >> 1);
  8.     printf("b right shift value is 0x%X\n", b >> 1);

  9.     return 0;
  10. }
输出结果为
  1. [root@Lnx99 test]#./a.out
  2. a right shift value is 0xC0000000
  3. b right shift value is 0x40000000
为什么结果不同呢?
查看汇编代码
  1. Dump of assembler code for function main:
  2. 0x080483c4 : push %ebp
  3. 0x080483c5 : mov %esp,%ebp
  4. 0x080483c7 : and $0xfffffff0,%esp
  5. 0x080483ca : sub $0x20,%esp
  6. 0x080483cd : movl $0x80000000,0x18(%esp)
  7. 0x080483d5 : movl $0x80000000,0x1c(%esp)
  8. 0x080483dd : mov 0x18(%esp),%eax
  9. 0x080483e1 : mov %eax,%edx
  10. 0x080483e3 : sar %edx
  11. 0x080483e5 : mov $0x80484e4,%eax
  12. 0x080483ea : mov %edx,0x4(%esp)
  13. 0x080483ee : mov %eax,(%esp)
  14. 0x080483f1 : call 0x80482f4
  15. 0x080483f6 : mov 0x1c(%esp),%eax
  16. 0x080483fa : mov %eax,%edx
  17. 0x080483fc : shr %edx
  18. 0x080483fe : mov $0x8048501,%eax
  19. 0x08048403 : mov %edx,0x4(%esp)
  20. 0x08048407 : mov %eax,(%esp)
  21. 0x0804840a : call 0x80482f4
  22. 0x0804840f : mov $0x0,%eax
  23. 0x08048414 : leave
  24. 0x08048415 : ret
  25. End of assembler dump.
其中红色代码对应的是a>>1,sar为算术右移,使用符号位补位,在这里补的全是1.
蓝色代码对应的是b>>1,shr为逻辑右移,使用0补位。

在平时的工作中,一般情况下,我们所期待的移位操作应该为逻辑右移,所以在使用移位操作时,一定要注意操作数的类型,一定要保证为无符号数。这样结果才是我们所期待的结果。

查了查资料,根据大多数的说法。C标准没有规定有符号数的右移如何处理。那么对于有符号数的右移处理,就由编译器决定。
阅读(3785) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~