意外的位移结果

时间:2014-06-06 16:34:28

标签: c++ c bit-manipulation

我有:

(gdb) display/t raw_data[4]<<8
24: /t raw_data[4]<<8 = 1111100000000
(gdb) display/t raw_data[5]
25: /t raw_data[5] = 11100111
(gdb) display/t (raw_data[4]<<8)|raw_data[5]
26: /t (raw_data[4]<<8)|raw_data[5] = 11111111111111111111111111100111

为什么第26行的结果不是0001111111100111?感谢。

编辑:更具体地说:

(gdb) display/t raw_data[5]
27: /t raw_data[5] = 11100111
(gdb) display/t 0|raw_data[5]
28: /t 0|raw_data[5] = 11111111111111111111111111100111

为什么第26行的结果不是11100111

3 个答案:

答案 0 :(得分:6)

您的数据类型为char,您的平台上似乎已签名。条目raw_data[5]包含负数-25。

打印格式t将数据打印为二进制的无符号整数。当您打印raw_data[5]时,它将转换为unsigned char 213,但只有8位。对数据执行整数运算时,字符将提升为32位整数。

将负字符值-25提升为有符号的int当然会产生-25,但它作为unsigned int的表示现在是2^^32 + x,而作为unsigned char则是2^^8 + x 。这就是32位二进制数开头的所有数据都来自的地方。

使用未签名的原始数据可能更好。

答案 1 :(得分:2)

让我们忽略第一个块,因为第二个块是最小的再现。

另请注意,0 | x会保留x的值,但会导致通常的整体促销。

然后第二个块并不是那么出乎意料。

(gdb) display/t raw_data[5]
27: /t raw_data[5] = 11100111

好的,raw_data[5]int8_t(-25)

(gdb) display/t 0|raw_data[5]
28: /t 0|raw_data[5] = 11111111111111111111111111100111

0|raw_data[5]int(-25)。实际上,价值得以保留。

答案 2 :(得分:0)

常量8导致促销为有符号整数,因此您在促销时也会看到符号扩展。将其更改为UINT8_C(8)。您需要为宏包含stdint.h。