I need to convert 2 bytes in char pcm[]
to a 1 byte short pcm_[]
. This post used a C-style cast, which at first I tried out in my C++ program (using 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();
}
I figured out that it only works if I use unsigned char
in the bit shifting, but do not understand, why this is necessary as the input is a char
.
Moreover, I would like to use C++-style-cast, and came up with this one:
short pcm_3 = (static_cast<unsigned char>(pcm[1])) << 8|
static_cast<unsigned char>(pcm[0]);
qDebug()<<pcm_3;
Again, I need to use unsigned char
instead of char
.
So I have 2 questions:
static_cast
the right cast? In my mind is an example from somewhere that used a reinterpret_cast
. However, the reinterpret cast does not work. unsigned char
? According to the C Standard (6.5.11 Bitwise exclusive OR operator)
3 The usual arithmetic conversions are performed on the operands
The same is written in the C++ Standard (5.13 Bitwise inclusive OR operator)
1 The usual arithmetic conversions are performed;
The usual arithmetic conversions include the integer promotions. This means that in this expression
( pcm[1] << 8 )| pcm[0];
operand pcm[0]
is promoted to type int
. If according to settings of your compiler type char
behaves like type signed char
then you get that value 0xA1
is promoted to signed int 0xFFFFFFA1
(provided that sizeof( int ) is equal to 4). That is the sign bit will be propogated.
Hence you will get an incorrect result. To avoid it you shoud cast type char
to type unsigned char
In this case the promoted value will look like 0x000000A1
. In C++ it can be written like
static_cast<unsigned char>( pcm[0] )
The problem starts here:
char pcm[2] = {0xA1, 0x12};
On your system, char
is signed, and has a range of -128
through 127
. You try to assign 161
to a char
. This is out of range.
In C and C++ the result of out-of-range assignment is implementation-defined . Usually, the compiler decides to go with the char with the same representation, which is -95
.
Then you promote this to int (by virtue of using it as operand of |
), giving the int value -95
which has a representation starting with lots of 1
bits.
If you actually want to work with the value 161
you will need to use a data type that can hold that value, such as unsigned char
. The simplest way is to make pcm[]
have that type, rather than using casts.
You have to use unsigned char
because of the promotion to int
with operator |
Assuming int
is 32 bits:
0xA1
becomes int 0xFFFFFFA1
(to keep same value) 0xA1
becomes 0x000000A1
. The reason you need to cast char
to unsigned char
is that char
is allowed to be a signed data type. In this case it would be sign-extended before performing the |
, meaning that the lower half would become negative for char
s with the most significant bit set to 1
:
char c = 200;
int a = c | 0; // returns -56 on systems where char is signed
In this example using static_cast
or the C cast is a matter of style. Many C++ shops stay away from C casts, because they are harder to find in the source code, while static_cast
s are much easier to spot.
A1
which is 10100001
you get 1111111110100001
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.