最近筆者一直在做JPEG的解碼工作,發現用完全使用哈夫曼樹進行解碼比較費時,而使用表結構存儲編碼和值的對應關系比較快捷,但是也存在比較難處理的地方,比如解碼工作通常是以位為單位的操作,這里必然會涉及到移位操作,而筆者之前對位的操作很少,經驗很欠缺,經過這次歷練終于發現了一個自己曾經忽視的東西,那就是C/C++中的移位操作容易出錯的情況。
1、什么樣的數據類型可以直接移位
char、short、int、long、unsigned char、unsigned short、unsigned int、unsigned long都可以進行移位操作,而double、float、bool、long double則不可以進行移位操作。
2、有符號數據類型的移位操作
對于char、short、int、long這些有符號的數據類型:
- 對負數進行左移:符號位始終為1,其他位左移
- 對正數進行左移:所有位左移,即 <<,可能會變成負數
- 對負數進行右移:取絕對值,然后右移,再取相反數
- 對正數進行右移:所有位右移,即 >>
3、無符號數據類型的移位操作
對于unsigned char、unsigned short、unsigned int、unsigned long這些無符號數據類型:
沒有特殊要說明的,使用<< 和 >> 操作符就OK了
結束語
8086 中存在邏輯移位、算術移位,而C\C++中的移位似乎既不是邏輯移位,也不是算術移位。
比如-1,我們若對它右移1位,C的結果仍舊是-1,事實上無論右移多少位始終是-1,邏輯移位得到的結果(8位表示)應該是-128,所以這點要注意
例子:
1.將 13800138000 轉為 91 68 31 08 10 83 00 F0 //91為+ 68國家號 不夠位長以F補
unsigned char *tt = new unsigned char[12];
strcpy((char*)tt,"13800138000");
tt[11] = 0xFF;
unsigned char *ss = new unsigned char[6];
cout << (tt[11]<<4) << endl;
memset(ss,0xFF,6);
int k=0;
for(int i=0; i<12; i=i+2)
{
ss[k++] = (tt[i+1]<<4)+(tt[i]&0x0F);
}
2. 將 整形 轉為 3位字節型16進制,如將 整型 888 轉為 16進制 00 03 78(Debug下有效,Release下無效) char param[4] = {0};
int iParamLen = 888;
param[0] = iParamLen >> 16;
param[1] = ((iParamLen >> 8) << 32) >> 32;
param[2] = (iParamLen << 32) >> 32;
反之
char param[4] = {0x00,0x03,0x78};
int ii1 = 0;
ii1 = param[0];
ii1 =ii1 << 8;
ii1 = ii1 | param[1];
ii1 =ii1 << 8;
ii1 = ii1 | param[2];