C / C++ 左移 右移 剖析

                                                                       C / C++  左移(<<) 右移(>>) 剖析

例子1 :

    char a = 0xF0;
    int  b = (int)a;
    int  c = 0xFFFFFFFF;
    int  d = c << 24;
    int  e = 0x80000010;
    int  f = e >> 1;
    printf("%d\n", b);
    printf("%d\n", d);
    printf("%d\n", c);
    printf("%d\n", e);
    getchar();

例子2 :

    char a = 0xF0;
    char b = a >> 2;
    printf("%d\n", a);
    printf("%d\n", b);
    getchar();

例子3 :

    char a = 0xF1;
    char b = a << 4;
    char c = 0xF0;
    char *b1 = &b;
    printf("%d\n", c);
    printf("%d\n", (a << 4));
    printf("%d\n", b);
    getchar();

例子4 :

    char a = 0x82;
    char b = a >> 1;
    printf("%d\n", a);
    printf("%d\n", b);
    getchar();

例子5 :

    char a = 0x42;
    char b = a << 1;
    char *b1 = &b;
    unsigned char c = b;
    printf("%d\n", a);                //66
    printf("%d\n", b);                //-124
    printf("%u\n", b);                //会被提升成unsigned int 0xFFFFFF84
    printf("%u\n", (unsigned char)b); //132
    printf("%u\n", c);                //132
    getchar();

例子6 :

    char a = 0x10;
    char b = a >> 1;
    printf("%d\n", a >> 1);//8
    printf("%d\n", b);     //8
    getchar();

 

注意 :C++ Primer 第五版 有如下说明

首先令左侧运算对象的内容按照右侧运算对象的要求移动指定位数,然后将经过移动的(可能还进行了提升)左侧

运算对象的拷贝作为求值结果。

运算对象可以是带符号的,也可以是无符号的。如果对象是带符号的且它的值为负,那么位运算如何处理运算对象

的“符号位”依赖于机器。而且此时的左移操作可能会改变符号位的值,因此是一种未定义的行为。

 

注意 :C语言深度剖析有如下说明

左移运算符“<<”是双目运算符。其功能把“<<”左边的运算数的各二进制全部左移若干位,由“<<”右边的数指定移动的

位数,高位丢弃,低位补0。

右移运算符“>>”是双目运算符。其功能是把“>>”左边的运算数的各二进制位全部右移若干位,“>>”右边的数指定移动

的位数。但注意:对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0;而为负数时,符号位为1,

最高位补0或是补1取决于编译系统的规定。Turbo C 和很多系统规定为补1。

 

个人看法:

其实不光Turbo C,我发现我用的vs2008也是规定为补1,至今我还没有见过补0的系统,所以很多东西还是有迹可循的,

故深入了解后,总结如下,来解释在这类系统下很多开发和调试时候的现象。

 

 

个人总结

一 、

先将a转换为补码, 即内存存储方式, 然后小整形一般会提升到4字节(正数补0,负数补1), 然后左移或者右移,然后有

强转发生强转,注意 : 一直都在操作内存中的补码,然后看你想把这个数,按有符号还是按无符号的形式展示出来(printf

打印、赋值或者强转成有符号无符号) :
1.1 用 无符号 的方式展示
编译器直接将补码当成源码去展示
1.2 用 有符号 方式展示
编译器通过查看补码的符号位来判断是正数还是负数,内存中,如果是正数(补码即源码),直接
展示,如果是负数转换为源码后在展示。

二 、

不带符号(非负):                                                 小整形转大整形时左补0,          左移时右补0, 右移时候左补0.

带符号的(负数):先转换成补码(内存方式),小整形转大整形时左补1(注意),左移时右补0, 右移时候左补1(注意).

注意, 大多数机器都左补1,很少机器左补0 (基于是1的补码还是2的补码)

 

--------------------------------欢迎大家评论和喷--------上述理解有何错误欢迎评论留言---万分感谢-------------------------

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值