[英]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.