1. 程式人生 > >詳解C++中的移位運算

詳解C++中的移位運算

移位運算:

  • 邏輯移位

邏輯移位是指邏輯左移和邏輯右移,移出的空位都用0來補。

  • 算術移位

算術移位 就需要分有符號型值和無符號型值

  1. 對於無符號型值,算術移位等同於邏輯移位。 
  2. 而對於有符號型值 ,算術左移等同於邏輯左移,算術右移補的是符號位,正數補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系列的編譯器中,對無符號型值進行移位時,預設是邏輯左移和邏輯右移;

而對於有符號型值進行移位時,左移還是邏輯左移,但右移時執行的是算術右移