将 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
(在您的系统上)的范围是 -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
.
当您将字符存储到 myChar
时,您存储的是大端字节序:先是高字节,然后是低字节。当您读出单个字节时,您正在以小端方式读取它们:首先是低字节,其次是高字节(移位 8,或乘以 256)。这就是为什么你得到这么大的价值。
myShort = (myChar[0] * 256) + myChar[1];
会给你预期的答案。
使用无符号类型进行位级操作。
例如,在具有 8 位字节的计算机上,char
是有符号的,myChar[0] = 0xE0
会产生负值。 在表达式中使用符号扩展。
相反,为避免出现问题,请对数字使用有符号类型。
编辑:
阅读评论后,感谢@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
(在您的系统上)的范围是 -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
.
当您将字符存储到 myChar
时,您存储的是大端字节序:先是高字节,然后是低字节。当您读出单个字节时,您正在以小端方式读取它们:首先是低字节,其次是高字节(移位 8,或乘以 256)。这就是为什么你得到这么大的价值。
myShort = (myChar[0] * 256) + myChar[1];
会给你预期的答案。
使用无符号类型进行位级操作。
例如,在具有 8 位字节的计算机上,char
是有符号的,myChar[0] = 0xE0
会产生负值。 在表达式中使用符号扩展。
相反,为避免出现问题,请对数字使用有符号类型。