我有:
(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
?
答案 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。