• C语言左移和右移


    事情的发生:

    某日工作中有个需求是将不同的数值存到char的前4位和后4位中。

    恰好同事中有同样取得32位int的前8位当成一个数值的代码:

    //取得32位中的高八位组成的值
    #define U32_HIGH_8(val)     ((val >> 24) & 0X000000FF)

    好奇心就来了,在右移24位以后是否还有必要再与上(&)0x000000FF将高位的数据彻底清零呢?

    讨论:

    考虑以下几个问题:

    (1)

    char i = 0x40; //二进制中i的表示为:0100 0000
    
    unsighed char j = 0x40;
    
    i <<= 1;
    
    j <<= 1;
    
    //问:i和j分别等于多少?

    i 左移以后的二进制表示为:1000 0000,由定义的有符号char解释为:i = -128

    j 左移以后的二进制表示为:1000 0000,由定义的无符号(unsigned char)解释为:i = 128

    (2)

    char i = 0x80;//二进制中表示为:1000 0000
    
    char j = 0x40;//二进制中i的表示为:0100 0000
    j >>= 1;
    
    i >>= 1;
    
    //问i和j等于多少?

    i 右移以后的二进制表示为:1100 0000(右移对于负数来说符号位右移,高位补1),故i=-64

    j 右移以后的二进制表示为:0010 0000(右移对于正数来说符号位右移,高位补0),故i=32

    (3)

    char i = -3;//二进制表示为:1111 1101    
    
    //i << 1是多少? i >> 1是多少?

    i << 1的二进制表示为:1111 1010(左移为逻辑左移高位丢弃,低位补0),由有符号数char解释为:-6

    i >> 1的二进制表示为:1111 1110(右移为算术右移,对于负数来说高位补1),有有符号数char解释为:2

    左移右移总结:

    右移左移涉及丢弃、补0或补1,但是最终对这一串二进制解释成什么数值是通过变量的定义(是否unsigned)来决定的。

    左移始终是逻辑左移,即丢弃高位,低位补0;

    右移是算术右移,对于有符号数:正数右移高位补0,负数右移高位补1。对于无符号数:逻辑右移(即高位补0,低位丢弃);

    结论:

    那么开头的问题是:是否还有必要再与上(&)0x000000FF将高位的数据彻底清零呢?

    我认为还是有必要的,因为并不知道值的类型是否是无符号数(unsigned),假如原本的32位数是普通的int类型且二进制为(1000 0000……0000 0000),那么取高8位的时候的二进制表示(1111 1111……1000 0000),那么这个数解释出来就会非常大且出错。如果是无符号数的话还算正常。

    因此为了避免日后定义错类型导致的错误,还是将移位以后的二进制的高位与上(&)0,将高位彻底清0为好。

  • 相关阅读:
    cstc2018 混合果汁
    CF1086E Beautiful Matrix
    AT2000 Leftmost Ball
    CF1208E Let Them Slide
    CF1208D Restore Permutation
    【置顶】博客公告
    [NOI2015]软件包管理器
    【noip2018】积木大赛
    几天连测总结
    【ZJOI2007】棋盘制作
  • 原文地址:https://www.cnblogs.com/jialin0x7c9/p/12158680.html
Copyright © 2020-2023  润新知