移位運算:
- 邏輯移位
邏輯移位是指邏輯左移和邏輯右移,移出的空位都用0來補。
- 算術移位
算術移位 就需要分有符號型值和無符號型值 :
- 對於無符號型值,算術移位等同於邏輯移位。
- 而對於有符號型值 ,算術左移等同於邏輯左移,算術右移補的是符號位,正數補0,負數補1。
其中,第2點涉及到負數在計算機中的存儲方式:
首先複習一下原碼、反碼、補碼:
有符號型值分爲正數和負數(包括正浮點數,和負浮點數),規定最高位爲符號位,正數爲0,負數爲1。
原碼:10進制轉換成2進制是原碼,只不過正數的原碼是本身符號位爲0,負數的原碼符號位爲1(1的原碼是0000 0001,-1的原碼是1000 0001)。
反碼: 正數的反碼是本身,負數的反碼是負數的原碼非符號位0變爲1,1變爲0(-1的原碼是1000 0001 它的反碼就是 1111 1110)。
補碼: 正數的補碼是本身,負數的補碼就是負數的反碼加1(-1的原碼是1000 0001,它的反碼就是 1111 1110 它的補碼就是 1111 1111)。
總結:正數的原碼,反碼 ,補碼三值合一, 負數的原碼,反碼,補碼不同。事實證明,計算機中負數是以補碼存儲的,也可以推廣到——計算機中所有數都是以補碼形式存儲的。
!!!補碼求原碼的過程,依然是(1)符號位不變,其它位取反;(2)符號位不參與計算,其餘加1。
詳見原文:負數在計算機中的存儲問題
因此,負數的算術右移,實際上是對補碼的右移。比如:
char i=-8;//原碼爲1000 1000,反碼爲1111 0111,補碼爲1111 1110;
i>>=3; //右移3位,即補碼右移3位,變成:
//補碼爲1111 1111,取反爲10000 0000,加1爲1000 0001,爲-1;
VS系列的編譯器中,對無符號型值進行移位時,默認是邏輯左移和邏輯右移;
而對於有符號型值進行移位時,左移還是邏輯左移,但右移時執行的是算術右移。