C語言左移和右移


事情的發生:

某日工作中有個需求是將不同的數值存到char的前4位和后4位中。

恰好同事中有同樣取得32位int的前8位當成一個數值的代碼:

//取得32位中的高八位組成的值
#define U32_HIGH_8(val)     ((val >> 24) & 0X000000FF)

好奇心就來了,在右移24位以后是否還有必要再與上(&)0x000000FF將高位的數據徹底清零呢?

討論:

考慮以下幾個問題:

(1)

char i = 0x40; //二進制中i的表示為:0100 0000

unsighed char j = 0x40;

i <<= 1;

j <<= 1;

//問:i和j分別等於多少?

i 左移以后的二進制表示為:1000 0000,由定義的有符號char解釋為:i = -128

j 左移以后的二進制表示為:1000 0000,由定義的無符號(unsigned char)解釋為:i = 128

(2)

char i = 0x80;//二進制中表示為:1000 0000

char j = 0x40;//二進制中i的表示為:0100 0000
j >>= 1;

i >>= 1;

//問i和j等於多少?

i 右移以后的二進制表示為:1100 0000(右移對於負數來說符號位右移,高位補1),故i=-64

j 右移以后的二進制表示為:0010 0000(右移對於正數來說符號位右移,高位補0),故i=32

(3)

char i = -3;//二進制表示為:1111 1101    

//i << 1是多少? i >> 1是多少?

i << 1的二進制表示為:1111 1010(左移為邏輯左移高位丟棄,低位補0),由有符號數char解釋為:-6

i >> 1的二進制表示為:1111 1110(右移為算術右移,對於負數來說高位補1),有有符號數char解釋為:2

左移右移總結:

右移左移涉及丟棄、補0或補1,但是最終對這一串二進制解釋成什么數值是通過變量的定義(是否unsigned)來決定的。

左移始終是邏輯左移,即丟棄高位,低位補0;

右移是算術右移,對於有符號數:正數右移高位補0,負數右移高位補1。對於無符號數:邏輯右移(即高位補0,低位丟棄);

結論:

那么開頭的問題是:是否還有必要再與上(&)0x000000FF將高位的數據徹底清零呢?

我認為還是有必要的,因為並不知道值的類型是否是無符號數(unsigned),假如原本的32位數是普通的int類型且二進制為(1000 0000……0000 0000),那么取高8位的時候的二進制表示(1111 1111……1000 0000),那么這個數解釋出來就會非常大且出錯。如果是無符號數的話還算正常。

因此為了避免日后定義錯類型導致的錯誤,還是將移位以后的二進制的高位與上(&)0,將高位徹底清0為好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM