[英]Bit shifting `char` vs. `unsigned char`
我需要将char pcm[]
中的2个字节转换为1个字节short pcm_[]
。 这篇文章使用了C样式的强制转换,起初我在C ++程序中尝试过(使用Qt):
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char pcm[2] = {0xA1, 0x12};
qDebug()<<pcm[0]<<pcm[1];
short pcm_ = ( pcm[1] << 8 )| pcm[0];
qDebug()<<pcm_;
short pcm_2 = ((unsigned char)(pcm[1])) << 8| (unsigned char) pcm[0];
qDebug()<<pcm_2;
return a.exec();
}
我发现只有当我在移位中使用unsigned char
它才有效,但不明白为什么这是必须的,因为输入是char
。
而且,我想使用C ++-style-cast,并提出了这一点:
short pcm_3 = (static_cast<unsigned char>(pcm[1])) << 8|
static_cast<unsigned char>(pcm[0]);
qDebug()<<pcm_3;
同样,我需要使用unsigned char
而不是char
。
所以我有两个问题:
static_cast
是否正确投放? 在我看来,是一个使用reinterpret_cast
的示例。 但是,重新解释强制转换不起作用。 unsigned char
? 根据C标准(6.5.11按位异或运算符)
3 The usual arithmetic conversions are performed on the operands
C ++标准(5.13按位包含或运算符)中编写了相同的内容
1执行通常的算术转换;
通常的算术转换包括整数提升。 这意味着在此表达式中
( pcm[1] << 8 )| pcm[0];
将操作数pcm[0]
提升为int
类型。 如果根据您的编译器的设置, char
类型的行为类似于signed char
类型,则您将值0xA1
提升为signed int 0xFFFFFFA1
(假设sizeof(int)等于4)。 那就是符号位将被传播。
因此,您将得到错误的结果。 为了避免这种情况,您应该将类型char
强制转换为unsigned char
类型。在这种情况下,提升后的值将看起来像0x000000A1
。 在C ++中可以这样写
static_cast<unsigned char>( pcm[0] )
问题从这里开始:
char pcm[2] = {0xA1, 0x12};
在您的系统上, char
是带符号的,范围为-128
到127
。 您尝试将161
分配给char
。 这超出范围。
在C和C ++中,超出范围分配的结果是实现定义的 。 通常,编译器决定使用具有相同表示形式的char -95
。
然后,将其提升为int(通过将其用作|
操作数),得到int值-95
,该值的表示形式以1
位开始。
如果您实际上想使用值161
,则需要使用可以保存该值的数据类型,例如unsigned char
。 最简单的方法是使pcm[]
具有该类型,而不是使用强制类型转换。
您必须使用unsigned char
因为升级为int
with operator |
假设int
是32位:
0xA1
变为int 0xFFFFFFA1
(保持相同的值) 0xA1
变为0x000000A1
。 您需要将char
为unsigned char
是,允许char
为有符号数据类型。 在这种情况下,将在执行|
之前对它进行符号扩展|
,这意味着对于最高有效位设置为1
char
,下半部分将变为负数:
char c = 200;
int a = c | 0; // returns -56 on systems where char is signed
在此示例中,使用static_cast
或C static_cast
是样式问题。 许多C ++商店都远离C强制转换,因为它们很难在源代码中找到,而static_cast
容易发现。
A1
即10100001
可以得到1111111110100001
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.