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

C++ unsigned characters not working as intended

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

这是我的功能

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,但是值 return 始终是“”。那我哪里错了?

注意:有时我得到的输出是0x80000000

我已经弄清楚问题了,希望:

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

(让我们假设 32 位整数)

根据this answer, 0x100 is actually a signed constant. Furthermore, according to implicit integer promotion rules

unsigned char or unsigned short can be converted to int if it can hold its entire value range, and unsigned int otherwise;

因此,H[0] 将被转换为 signed int,因此整个表达式是有符号的,所以 H[0] of 0x89 将导致尝试获取 (signed int) (0x89000000) 的值,或者换句话说,您将遇到整数溢出 undefined behaviour,在您的情况下,这会给您一个意想不到的负值。

正如我在评论中提到的,将四个无符号字节转换为无符号整数的规范方法是:

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:请不要对其他用户无礼 - 当我看到你的评论时,我差点删除了这个答案。