将 char[2] 转换为 unsigned short 时出错?

Error converting char[2] to unsigned short?

编辑:

阅读评论后,感谢@M.M 和@AnttiHaapala 我修复了我的代码,但仍然得到不正确的输出...

新代码:

#include <iostream>
int main() {
    char * myChar;
    myChar = new char[2];
    myChar[1] = 0x00;
    myChar[0] = 0xE0;
    unsigned short myShort;
    myShort = ((myChar[1] << 8) | (myChar[0]));
    std::cout << myShort << std::endl;
    return 0;
}

输出:

65504

或者如果您颠倒顺序

57344

旧Post:

所以我有一个从文件中读取的两个字节的值,我想将其转换为无符号短整型,以便我可以使用该数值。

示例代码:

#include <iostream>
int main() {
    char myChar[2];
    myChar[1] = 'à';
    myChar[0] = '[=13=]';
    unsigned short myShort;
    myShort = ((myChar[1] << 8) | (myChar[0]));
    std::cout << myShort << std::endl;
    return 0;
}

输出:

40960

但是 à[=17=]E0 00 应该有一个值 224 作为一个无符号的两字节值?

也很有意思...

此代码:

include <iostream>
int main() {
    char * myChar;
    myChar = "[=15=]à";
    unsigned short myShort;
    myShort = ((myChar[1] << 8) | (myChar[0]));
    std::cout << myShort << std::endl;
    return 0;
}

输出:

49920

注意: 原始代码有一个复杂的因素,因为源是 UTF-8 编码的。请检查此答案的编辑历史以查看我对此的评论。但是我认为这不是您要问的主要问题,因此我更改了答案以仅解决编辑问题。为避免 UTF-8 转换问题,请使用 '\xE0' 而不是 'à'.


关于编辑后的代码:

char * myChar;
myChar = new char[2];
myChar[1] = 0x00;
myChar[0] = 0xE0;
unsigned short myShort;
myShort = ((myChar[1] << 8) | (myChar[0]));
std::cout << myShort << std::endl;

char(在您的系统上)的范围是 -128127。这很常见。你写 myChar[0] = 224;。 (0xE0 是一个 int 字面量,值为 224)。

这是一个超出范围的转换,它会导致实现定义的行为。最常见的是,实现将定义它以调整模 256 直到值在范围内。所以你最终得到与以下相同的结果:

myChar[0] = -32;

那么计算(myChar[1] << 8) | myChar[0]就是0 | (-32),也就是-32。最后,你转换为 unsigned short。这是另一个超出范围的转换,因为unsigned short的范围在您的系统上是[0, 65535]

但是,在这种情况下,到无符号类型的超出范围的转换明确定义为调整模 65536,因此结果为 65536 - 32 = 65504.


颠倒顺序执行 ((-32) << 8) | 0。左移负值会导致 未定义的行为 ,尽管在您的系统上它已表现为 -32 * 256,给出 -8192。将其转换为 unsigned short 得到 65536 - 8192 = 57344.


如果您试图从第一个示例中获得 224,最简单的方法是使用 unsigned char 而不是 char。然后 myChar[0] 将保存值 224 而不是值 -32.

当您将字符存储到 myChar 时,您存储的是大端字节序:先是高字节,然后是低字节。当您读出单个字节时,您正在以小端方式读取它们:首先是低字节,其次是高字节(移位 8,或乘以 256)。这就是为什么你得到这么大的价值。

myShort = (myChar[0] * 256) + myChar[1];

会给你预期的答案。

使用无符号类型进行位级操作。

例如,在具有 8 位字节的计算机上,char 是有符号的,myChar[0] = 0xE0 会产生负值。 在表达式中使用符号扩展

相反,为避免出现问题,请对数字使用有符号类型。