在C中链接位移运算符后出现意外结果

时间:2016-09-13 09:06:48

标签: c bit-shift

我无法弄清楚为什么链接位移操作不会返回与不链接它们相同的结果。

#include <stdio.h>

void bit_manip_func(unsigned char byte)
{
    unsigned char chain = (((byte >> 3) << 7) >> 3);
    printf("%d\n", chain); //this prints 144

    unsigned char o1 = byte >> 3;
    unsigned char o2 = o1 << 7;
    unsigned char o3 = o2 >> 3;
    printf("%d\n", o3); //this prints 16 as expected
}

int main()
{
    //expecting both printf's to print
    //the same value (16).
    bit_manip_func(73);
    return 0;
}

我希望两个printf调用打印出16,因为二进制中的73是0100 1001.应用byte >> 3后,我应该得到0000 1001,(byte >> 3) << 7结果之后是1000 0000,在(((byte >> 3) << 7) >> 3)之后,结果应该是0001 0000,当然是16.实际上发生了什么?

2 个答案:

答案 0 :(得分:5)

运营商&gt;&gt;和&lt;&lt;对其操作数执行整数提升。因此,当与任一运算符一起使用时,unsigned char类型被提升为int。

在下一行中,变量字节被提升为int类型,然后对此类型执行所有三个操作:

unsigned char chain = (((byte >> 3) << 7) >> 3);

因此保留了设置为1的最左位:

01001001 => 01001 => 010010000000 => 010010000 
 ^           ^        ^               ^

在下面的代码中,变量被提升为int类型,但是在每次操作之后,具有int类型的结果被分配给unsigned char并因此包装(最重要的位被删除),
因为你的平台上unsigned char的范围是[0,2 ^ 8-1]。

unsigned char o1 = byte >> 3;
unsigned char o2 = o1 << 7;
unsigned char o3 = o2 >> 3;

这意味着不保留设置为1的最左位:

01001001 => 01001 => 10000000 => 000010000
 ^           ^       

答案 1 :(得分:2)

unsigned char chain = (((byte >> 3) << 7) >> 3);

((byte >> 3) << 7)被提升为int,然后对>> 3

执行int

包裹到unsigned char(mod 256),您获得((73 >> 3) << 7) >> 3) % 256 = 144

使用演员:

unsigned char chain = ((unsigned char)((byte >> 3) << 7) >> 3);