算術右移 邏輯右移

先由一道題目引入:有兩個變量a和b,不用if、?:、switch等判斷語句,找出較大的那個變量。html

其中一種答案以下:spa

?
1
2
3
4
char * result[] = { "a is larger" , "b is larger" };
int  c = a - b;
c = unsigned(c) >> ( sizeof ( int ) * 8 - 1);
cout << result[c] << endl;

 sizeof(int) * 8 很好理解,就是求出int型佔內存的bit數,-1就是爲了右移後保留最高位,即保留符號位。指針

 問題來了:爲何移位時要把c轉爲unsigned呢?而一旦去掉unsigned關鍵字的話運行出錯。調試

 在vc2008中設置斷點,調試,進入反彙編,發現問題出如今 >> 時,若是c爲-1,則EAX(32位寄存器) = 0xffffffff,沒有unsigned狀況下移位後仍是0xffffffff。code

?
//c = c >> (sizeof(int) * 8 - 1);
004114F3  mov         eax,dword ptr [c]
004114F6  sar         eax,1Fh
004114F9  mov         dword ptr [c],eax

 而有unsigned的話移位後則爲0x00000001。htm

?
//c = unsigned(c) >> (sizeof(int) * 8 - 1);
004114F3  mov         eax,dword ptr [c]
004114F6  shr         eax,1Fh
004114F9  mov         dword ptr [c],eax

 c右移的規則是:無符號數右移時左邊高位移入0;有符號數右移時:1.符號位爲0,移入0;2.符號位爲1,有的系統移入1(算術右移),有的系統移入0(邏輯右移)blog

 經驗證vc和gcc均默認爲算術右移,上面的彙編代碼也說明了這一點,有unsigned時右移採用的是shr(shift logical right)邏輯右移,無unsigned時採用sar(shift arithmetic right)算術右移。內存

 《c和指針》中也建議不要對有符號數進行>>操做,因此爲了確保結果必定,>>時把數值轉成unsignedci

 又試了一下<<,發現signed和unsigned都是採用shl邏輯左移,應該是shl和sal效果都同樣,因此編譯器就統一採用shl。get

 試驗int 0x80000000 << 1結果爲0,說明符號位對左移沒影響。

相關文章
相關標籤/搜索