我一直处理无符号数字,但由于一些奇怪的原因,他们没有使用此代码。
这是我的功能
string compare (unsigned char H[4])
{
unsigned int sum = H[3] + H[2] * 0x100 + H[1] * 0x100 * 0x100 + H[0] * 0x100 * 0x100 * 0x100;
switch(sum)
{
case 0x414b4220: return "akb"; break;
case 0x89425446: return "png"; break;
case 0xefbbbf3c: return "plist"; break;
case 0x4c574600:
case 0x5df90000: return "lwf"; break;
case 0x4a4d5000:
case 0x424d4900:
case 0x434c5300:
case 0x43485000:
case 0x53544700:
case 0x4d415000: return "bin"; break;
default: return "";
}
}
正在以这种方式调用该函数:
unsigned char C[4];
fin2>>C[0]>>C[1]>>C[2]>>C[3];
string ext = compare(C);
我得到的sum值的输出总是0x89425446,但值返回总是“”。那么我哪里出错?
注意:有时我得到的输出是0x80000000
答案 0 :(得分:4)
我想出了问题,我希望:
H[0] * 0x100 * 0x100 * 0x100
(我们假设32位整数)
根据this answer,0x100
实际上是一个有符号常数。此外,根据implicit integer promotion rules:
unsigned char或unsigned short如果可以保存其整个值范围,则可以转换为int,否则可以转换为unsigned int;
因此,H[0]
将转换为 signed int,因此整个表达式都已签名,因此H[0]
的{{1}}将导致尝试获取0x89
的值,换句话说,您将有一个整数溢出undefined behaviour,在您的情况下会给您一个意外的负值。
正如我在评论中提到的,将四个无符号字节转换为无符号整数的规范方法是:
(signed int) (0x89000000)
这明确地将unsigned int sum = (unsigned int) H[3]
| ((unsigned int) H[2] << 8)
| ((unsigned int) H[1] << 16)
| ((unsigned int) H[0] << 24);
提升为H[]
,并使用unsigned int
转换避免了意外转换标记的问题。
PS:请不要对其他用户不礼貌 - 当我看到你的评论时,我几乎删除了这个答案。