阅读完评论后,感谢@ 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
但à\0
或E0 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
答案 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
(在您的系统上)的范围是-128
到127
。这很常见。你写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];
会给你预期的答案。