我还没有找到回答这种确切行为的问题,不知何故,我只是不明白发生了什么:
我将 Windows 位图文件 (bmp) 的内容读入数组,稍后使用此数组提取所需信息:
char biHeader[40];
// ...
source.read(biHeader,40);
// ...
int biHeight = biHeader[8] | (biHeader[9] << 8) | (biHeader[10] << 16) | (biHeader[11] << 24);
在此之后,biHeight
显示为-112
这是完全错误的,因为它应该是400
的。所以,我看了一下该文件的十六进制转储。阅读的内容是:
90 01 00 00
将字节顺序更改为大端序会得到0x190
,该400
以十进制表示,正如预期的那样。
如果我将上面的代码更改为:
unsigned char biHeader[40];
// ...
source.read((char*)biHeader,40);
// ...
int biHeight = ... (same as before)
。然后我得到预期值。这是怎么回事?
以及:您将如何读取这些数据?
作为有符号 8 位二进制补码整数,0x90
是 -112
。当它被转换为|
的int
时,它的值被保留。由于如果表示形式是 2 的补码,则设置从第七位开始的所有位,因此按位或值向左移动至少 8 位不会再更改该值。
作为无符号 8 位整数,0x90
的值为 144,这是一个正数,没有超出 2^7
位设置的位。然后,按位或带biHeader[9] << 8
将值更改为所需的144 + 256 = 400
。
使用按位运算符时,(几乎)总是使用无符号类型,有符号类型通常会导致令人不快的意外(如果移位结果超出范围或负整数向左移动,则会导致未定义的行为)。