C++无符号字符无法按预期工作



我一直在处理无符号数字,但由于一些奇怪的原因,它们在这段代码中不起作用。

这是我的功能

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

我已经解决了问题,我希望:

H[0] * 0x100 * 0x100 * 0x100

(假设32位整数)

根据这个答案,0x100实际上是一个有符号的常数。此外,根据隐式整数提升规则:

如果无符号char或无符号short可以保持其整个值范围,则可以转换为int,否则可以转换为无符号int;

因此,H[0]将被转换为有符号的int,因此整个表达式都是有符号的,因此0x89H[0]将导致尝试获取值(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,并且使用<<移位可以避免意外的符号转换问题。

附言:请不要对其他用户无礼——当我看到你的评论时,我差点删除了这个答案。

相关内容

  • 没有找到相关文章

最新更新