在C语言中链接位移操作符后出现意外结果



我不明白为什么链接位移操作不返回与不链接它们相同的结果。

#include <stdio.h>
void bit_manip_func(unsigned char byte)
{
    unsigned char chain = (((byte >> 3) << 7) >> 3);
    printf("%dn", chain); //this prints 144
    unsigned char o1 = byte >> 3;
    unsigned char o2 = o1 << 7;
    unsigned char o3 = o2 >> 3;
    printf("%dn", 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 000,应用(((byte >> 3) << 7) >> 3)后,结果应该是0001 000,当然是16。到底发生了什么?

操作符>>和<<对其操作数执行整数提升。因此,当与任意一个操作符一起使用时,unsigned char类型将提升为int。

在下一行中,变量byte被提升为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
 ^           ^       

In

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

((byte >> 3) << 7)被提升为int,然后它在int上执行>> 3

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

使用强制转换:

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

最新更新