Dan*_*our 1 c c++ file-io serialization type-conversion
我还没有找到回答这个确切行为的问题,而且我只是不知道发生了什么:
我将Windows位图文件(bmp)的内容读取到一个数组中,并在以后使用此数组提取所需的信息:
char biHeader[40];
// ...
source.read(biHeader,40);
// ...
int biHeight = biHeader[8] | (biHeader[9] << 8) | (biHeader[10] << 16) | (biHeader[11] << 24);
Run Code Online (Sandbox Code Playgroud)
此后,biHeight显示,-112因为应该是完全错误400。因此,我看了一下文件的十六进制转储。读取的内容是:
90 01 00 00
Run Code Online (Sandbox Code Playgroud)
更改字节顺序大端给人0x190这是400十进制,符合市场预期。
如果我将以上代码更改为:
unsigned char biHeader[40];
// ...
source.read((char*)biHeader,40);
// ...
int biHeight = ... (same as before)
Run Code Online (Sandbox Code Playgroud)
...然后我得到了期望值。这里发生了什么?
并且:您将如何读取这些数据?
作为带符号的8位二进制补码整数,0x90是-112。当被转换成int的|,它的价值将被保留。由于如果表示形式为二进制补码,则从第七位起的所有位都将置位,因此按位或左移至少八位的值不再更改该值。
作为无符号的8位整数,其值为0x90144,这是一个正数,没有超出该2^7位设置的位。然后,按位或与biHeader[9] << 8将该值更改为所需的144 + 256 = 400。
当使用按位运算符时,(几乎)总是使用无符号类型,有符号类型通常会导致令人不快的意外(如果移位结果超出范围或向左移负整数,则会导致不确定的行为)。