C语言中位移问题

声明:
本文原创,一部分内容引用其他人博客,有个错字,进行修复一下,本人特别讨厌各种无理由复制粘贴,本篇文章只作为自己参考使用,如有侵权,请原作联系本人。

博客链接

逻辑位移与算数位移
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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章