我没有找到回答这个确切行为的问题,不知怎的,我只是不明白发生了什么:
我将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
。
所以,我看了一下该文件的hexdump。阅读的内容是:
90 01 00 00
将字节顺序更改为big endian会得到0x190
,其中十进制为400
,如预期的那样。
如果我将上述代码更改为:
unsigned char biHeader[40];
// ...
source.read((char*)biHeader,40);
// ...
int biHeight = ... (same as before)
...然后我得到了预期的价值。这是怎么回事?
并且:你会如何阅读这些数据?
答案 0 :(得分:5)
作为带符号的8位二进制补码整数,0x90
为-112
。如果int
转换为|
,则会保留其值。由于如果表示是二进制补码,则设置第七个开启的所有位,按位或向左移动至少八位的值不再改变该值。
作为无符号8位整数,0x90
的值为144,为正数,没有超出2^7
位设置的位。然后,按位或biHeader[9] << 8
将值更改为所需的144 + 256 = 400
。
当使用按位运算符时,(几乎)总是使用无符号类型,有符号类型通常会导致令人不快的意外(如果移位结果超出范围或负整数向左移位,则会出现未定义的行为)。