意外的位移位结果



我有:

(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

您的数据类型是char,在您的平台上看起来是签名的。条目raw_data[5]保存的是负数-25。

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

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

使用无符号的原始数据可能更好。

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

还需要注意的是,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)

常数8导致提升为有符号整数,因此您在提升中也看到了符号扩展。将其改为UINT8_C(8)。您需要为宏包含stint .h。

最新更新