我不明白为什么链接位移操作不返回与不链接它们相同的结果。
#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);