[c語言]左移和右移


左移和右移都是位運算的概念。我們知道計算機是基於二進制保存數據的,因此左移和右移的概念十分重要。本文約定是32位的機器。

 

[左移] 丟棄最高位,0補最低位

左移是把一個數按照二進制每位向左移動若干位,在c語言中用運算符 << 表示。例如:

int x = 1;
x = x << 2; //把x的值左移2位

 

1對應的二進制數為000……0001(前面一共31個0),左移2位之后變成000……0100,在十進制下為4。所以看起來左移n位相當於乘以2的n次方。(有符號數不完全適用,因為左移有可能導致符號的變化,下面將給出解釋)

 

需要注意的是,當左移結果超出數據類型所能表示的范圍時,會出現溢出(產生數據丟失並造成結果錯誤)。我們知道,int是有符號的整型數,最高位是符號位,0表示正數,1表示負數。那么移位的時候就會出現溢出,例如:

int x = 0x40000000; //16進制的40000000,為2進制的0100……0000
x = x << 1;

 

這時候,x左移1位之后變成0x80000000,也就是2進制的1000……0000,符號位被置為1,變成了int型變量所能表示的最小值(因為負數是用補碼表示的,計算補碼:取反后加1),這個值在十進制下為-2147483648,我們成為溢出。如果把這個x再繼續左移1位,那么最高位被丟棄,最低位補0,x的值就變成了0。這看起來是一件有意思的事情,由此可見,左移簡單的理解為乘2的冪是不准確的。

 

左移中有一個比較特殊的情況,當左移的位數超過該數值類型的最大位數的時候,編譯器會先用左移的位數對最大位數取模,然后按照余數進行移位計算。例如:

int x = 1, y = 0x80000000; //y的值在二進制下是1000……0000
x = x << 33; //33 % 32 = 1 左移1位,x變成2
y = y << 33; //33 % 32 = 1 左移1位,最高位被丟棄,y變成0

 

在用gcc編譯這段程序的時候,編譯器會給出一個warning,意思是 左移位數>=類型長度。事實上,上面這個例子x和y都是左移了1位,也就是33%32后的余數。(這個規則與編譯器有關,不同的編譯器可能處理方式不一樣)
 
[右移] 丟棄最低位,符號補高位
右移的概念和左移正好相反,是指的向右移動若干位,在c語言中用運算符 << 表示。
 
相比較左移來說,右移稍稍復雜一點。我們分為 有符號整數 和 無符號整數 來說明。
 
對於無符號整數,右移可以直接看做是除以2的n次方的運算,且有整數除法的概念,低位移出去的位全部丟棄。舉個簡單的例子來說,十進制的5對應的二進制的表示為101,它右移1位得到的數會是2,也就是二進制表示的10,右端的1直接被丟棄掉了。
 
對於有符號整數,右移會保持符號位不變。例如:
int x = 0x80000000; //對應二進制的1000……0000
x = x >> 1; //x的值不會變成0x40000000(二進制的0100……0000),而是變成0xc0000000(二進制的1100……0000)

也就是說,符號位向右移動后,如果之前是正數,就在最高位補0;如果是負數,就在最高位補1(這樣的方式還是與負數用補碼存儲有關)。這也是匯編語言中的算術右移。

 

同樣的,當移動的位數超過類型的長度的時候,會先取余數,然后移動余數位。

 

這里值得指出的是,在c語言中,左移是邏輯/算數左移(兩者完全相同),右移是算術右移,會保持符號位不變。

 


免責聲明!

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



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