C ++无符号字符无法正常工作

时间:2017-01-19 02:51:42

标签: c++ signed

我一直处理无符号数字,但由于一些奇怪的原因,他们没有使用此代码。

这是我的功能

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

1 个答案:

答案 0 :(得分:4)

我想出了问题,我希望:

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

(我们假设32位整数)

根据this answer0x100实际上是一个有符号常数。此外,根据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:请不要对其他用户不礼貌 - 当我看到你的评论时,我几乎删除了这个答案。