位移`char`与`unsigned char`

时间:2015-07-19 11:38:19

标签: c++ casting bit-shift

我需要将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

5 个答案:

答案 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已签名,其范围为-128127。您尝试将161分配给char。这超出了范围。

在C和C ++中,超出范围分配的结果是实现定义的。通常,编译器决定使用具有相同表示形式的char,-95

然后将此提升为int(通过将其用作|的操作数),给出int值-95,其具有以大量1位开头的表示。 / p>

如果您确实想使用值161,则需要使用可以保存该值的数据类型,例如unsigned char。最简单的方法是让pcm[]具有该类型,而不是使用强制转换。

答案 2 :(得分:0)

您必须使用unsigned char,因为int促销operator |

假设int是32位:

  • signed char 0xA1变为int 0xFFFFFFA1(保持相同的值)
  • unsigned char 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)

  1. 您应该将数据类型转换为无符号,因为当您将已签名的字符“展开”为有符号的短时,它的第7位将被复制到short的第8-15位。 因此,从A1 10100001得到1111111110100001
  2. 根据this question and answer,reinterpret_cast是你应该想到的最后一个演员。