我需要将char pcm[]
中的2个字节转换为1个字节short pcm_[]
。 This帖子使用了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
?答案 0 :(得分:3)
根据C标准(6.5.11按位异或运算符)
3 The usual arithmetic conversions are performed on the operands
C ++标准(5.13按位包含OR运算符)
中写的相同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] )
答案 1 :(得分:1)
问题从这里开始:
char pcm[2] = {0xA1, 0x12};
在您的系统上,char
已签名,其范围为-128
到127
。您尝试将161
分配给char
。这超出了范围。
在C和C ++中,超出范围分配的结果是实现定义的。通常,编译器决定使用具有相同表示形式的char,-95
。
然后将此提升为int(通过将其用作|
的操作数),给出int值-95
,其具有以大量1
位开头的表示。 / p>
如果您确实想使用值161
,则需要使用可以保存该值的数据类型,例如unsigned char
。最简单的方法是让pcm[]
具有该类型,而不是使用强制转换。
答案 2 :(得分:0)
您必须使用unsigned char
,因为int
促销operator |
假设int
是32位:
0xA1
变为int 0xFFFFFFA1
(保持相同的值)0xA1
变为0x000000A1
。答案 3 :(得分:0)
您需要将char
强制转换为unsigned char
的原因是char
被允许为签名数据类型。在这种情况下,它会在执行|
之前进行符号扩展,这意味着char
的下半部分将变为负数,其中最重要的位设置为1
:
char c = 200;
int a = c | 0; // returns -56 on systems where char is signed
在此示例中,使用static_cast
或C cast是一种风格问题。许多C ++商店远离C版,因为它们在源代码中很难找到,而static_cast
更容易被发现。
答案 4 :(得分:0)
A1
10100001
得到1111111110100001
。