将char [2]转换为无符号短整数时出错?

时间:2016-03-25 04:40:18

标签: c++ type-conversion byte short endianness

编辑:

阅读完评论后,感谢@ 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

旧帖子:

所以我有一个两个字节的值,我正在从一个文件中读取,并希望转换为无符号短,所以我可以使用数值。

示例代码:

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

输出:

40960

à\0E0 00的值应为224,作为无符号的双字节值?

也很有意思......

此代码:

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

输出:

49920

3 个答案:

答案 0 :(得分:3)

注意:原始代码的一个复杂因素是源是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

答案 1 :(得分:1)

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

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

相反,为避免出现问题,请使用签名类型作为数字。

答案 2 :(得分:0)

当您将角色存储到myChar时,您将其存储为big-endian:首先是高字节,然后是低字节。当你读出单个字节时,你将它们读作little-endian:低字节优先,高字节秒(移位8,或乘以256)。这就是你获得这么大价值的原因。

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

会给你预期的答案。