声明:
本文原创,一部分内容引用其他人博客,有个错字,进行修复一下,本人特别讨厌各种无理由复制粘贴,本篇文章只作为自己参考使用,如有侵权,请原作联系本人。
博客链接
逻辑位移与算数位移
http://www.cnblogs.com/hnrainll/archive/2011/07/06/2099068.html
正文
在C语言中,涉及位移的运算符有2个,>>表示右移,<<则表示左移。
而汇编指令中,SHL和SHR表示逻辑左移和逻辑右移,SAR和SAL表示算术左移和算术右移。其中,逻辑左移和算术左移都是寄存器二进制位整体向左移动,并在右边补0。
而右移则不同,逻辑右移是整体向左移,并在左边补0
而算术右移则是根据原符号位的值补与其相同的值。根据C标准,如果在位移运算符左边的变量是有符号数,如int,char,short等,编译产生的 汇编指令是算术位移指令,如果该变量是无符号数,如unsigned int,unsigned char等,编译产生的汇编指令则是逻辑位移指令
本文只解释右移,因为左移比较简单
例子:
unsigned int a = -1;
int b = -1;
a = a >> 2;
b = b >> 2;
printf("%x\n", a);
printf("%x\n", a);
printf("%x \n", b);
printf("%x \n", b);
结果:
3fffffff
3fffffff
ffffffff
ffffffff
解释:
计算机存储负数补码,取反加1,不明白同学查询下,不细讲-1
二进制: 0000000000000000000000000000001
取反后: 11111111111111111111111111111110
+1存储: 11111111111111111111111111111111无符号位移为逻辑位移
右移2位左侧补0:00111111111111111111111111111111有符号位移为算数位移
右移2位,左侧补算数位1:111111111111111111111111111111111
扩展:
printf("%u\n", a);
printf("%d\n", a);
printf("%u \n", b);
printf("%d \n", b);
结果:
1073741823
1073741823
4294967295
-1
有些同学对上面的结果表示不明白
%u , %d
为格式化符
在输出的时候按照提供的格式进行了格式化
a 的二进制形式3fffffff
当输出为u的时候,作为无符号正常输出,
输出为%d的时候,作为有符号输出,
有符号第一位代表符号位,0代表正数,正数的补码和原码是一致的。b 的二进制形式
ffffffff
当输出为u的时候,作为无符号正常输出,
输出为%d的时候,作为有符号输出,
有符号第一位代表符号位,1代表正数,负数的补码与原码转换需要取反加1。