我还没有找到回答这个确切行为的问题,不知何故我只是不明白发生了什么:
我将 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)
...然后我得到预期值。这是怎么回事?
并且:您将如何读取这些数据?
最佳答案
作为带符号的 8 位二进制补码整数,0x90
是-112
.当转换为 int
时对于 |
,它的值(value)得以保留。如果表示是二进制补码,则从第七位开始的所有位都会被设置,因此按位或将值左移至少八位不会再更改值。
作为无符号 8 位整数,0x90
的值是 144,一个正数,没有超过 2^7
的位位设置。然后,按位或 biHeader[9] << 8
将值更改为所需的 144 + 256 = 400
.
当使用按位运算符时,(几乎)总是使用无符号类型,有符号类型通常会导致令人不快的意外(如果移位结果超出范围或负整数左移,则会出现未定义的行为)。
关于c++ - C/C++ : Conversion of char[] to int fails, unsigned char[] to int 有效,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13786921/