博客:linuxfocus.blog.chinaunix.net
(下面所有的测试为Linux平台,gcc编译器)
-
#include <stdio.h>
-
#include <stdlib.h>
-
-
-
int main ()
-
{
-
int a = 0x80000000;
-
unsigned int b = 0x80000000;
-
-
printf("a right shift value is 0x%X\n", a >> 1);
-
printf("b right shift value is 0x%X\n", b >> 1);
-
-
return 0;
- }
输出结果为
-
[root@Lnx99 test]#./a.out
-
a right shift value is 0xC0000000
- b right shift value is 0x40000000
为什么结果不同呢?
查看汇编代码
- Dump of assembler code for function main:
-
0x080483c4
: push %ebp -
0x080483c5
: mov %esp,%ebp -
0x080483c7
: and $0xfffffff0,%esp -
0x080483ca
: sub $0x20,%esp -
0x080483cd
: movl $0x80000000,0x18(%esp) -
0x080483d5
: movl $0x80000000,0x1c(%esp) -
0x080483dd
: mov 0x18(%esp),%eax -
0x080483e1
: mov %eax,%edx -
0x080483e3
: sar %edx -
0x080483e5
: mov $0x80484e4,%eax -
0x080483ea
: mov %edx,0x4(%esp) -
0x080483ee
: mov %eax,(%esp) -
0x080483f1
: call 0x80482f4 -
0x080483f6
: mov 0x1c(%esp),%eax -
0x080483fa
: mov %eax,%edx -
0x080483fc
: shr %edx -
0x080483fe
: mov $0x8048501,%eax -
0x08048403
: mov %edx,0x4(%esp) -
0x08048407
: mov %eax,(%esp) -
0x0804840a
: call 0x80482f4 -
0x0804840f
: mov $0x0,%eax -
0x08048414
: leave -
0x08048415
: ret - End of assembler dump.
其中红色代码对应的是a>>1,sar为算术右移,使用符号位补位,在这里补的全是1.
蓝色代码对应的是b>>1,shr为逻辑右移,使用0补位。
在平时的工作中,一般情况下,我们所期待的移位操作应该为逻辑右移,所以在使用移位操作时,一定要注意操作数的类型,一定要保证为无符号数。这样结果才是我们所期待的结果。
查了查资料,根据大多数的说法。C标准没有规定有符号数的右移如何处理。那么对于有符号数的右移处理,就由编译器决定。