2009-06-26 133 views
7

爲什麼(-1 >> 1)結果-1?我在C工作,但我認爲這不重要。(-1 >> 1)== -1 - 爲什麼?

我想不通,我錯過了什麼?

這裏是一個C程序,它的計算的一個例子:

#include <stdio.h> 



int main() 
{ 
    int num1 = -1; 

    int num2 = (num1 >> 1); 

    printf("num1=%d", num1); 

    printf("\nnum2=%d", num2); 

    return 0; 
} 
+1

在php「echo -1 >> 1中也是如此;」 – merkuro 2009-06-26 01:42:57

+0

也在python中,正如答案所說,負數填充1以保留符號是有意義的。 – 2009-06-26 01:45:40

回答

23

由於帶符號整數表示爲two's complement表示法。

-111111111(如果它是一個8位的數字)。

-1 >> 1顯然符號擴展,使之保持11111111。這種行爲取決於編譯器,但對於Microsoft,在移位有符號數字權限(>>)時複製符號位,而移動無符號數字權限會導致0被置於最左邊的位。

5

位移負數是C.執行行爲的結果將取決於你的平臺上,理論上可能是完全荒謬的。從C99的標準(6.5.7.5):

E1 >> E2的結果是E1 右移E2位的位置。如果E1 具有無符號類型或者如果E1具有 有符號型和非負值,則 結果的值是 E1/ 2^E2的商的整數部分。如果E1具有帶符號的類型和 負值,則結果值爲 實現定義。

發生這種情況的原因很可能是因爲您的編譯器使用x86 SAR(Shift Arithmetic Right)指令來實現>>。這意味着會發生符號擴展 - 一旦數值被移位,最重要的位將被複制到新的MSB中。從intel manuals

移位算術右移(SAR)和 移位邏輯右(SHR)的指令 目的地 操作數的比特移位到右側(朝向更少 顯著位位置)。對於每個 移位計數,目標操作數的最低有效位 將 移位到CF標誌中,並且最重要的位爲 或者 取決於指令 類型。在SHR指令清除 最顯著位(見圖7-8 在64和IA-32 架構軟件開發人員 手冊,卷1); SAR指令 設置或清除最顯著 比特以對應於所述目的地操作數的原始值 的符號(最 顯著位)。 實際上, SAR指令填充所述空 比特位置與未移位值的 符號(參見 圖7-9中的64和IA-32 架構軟件開發人員 手冊,第1卷移位值)。

+1

引用的段落指出像(10 >> -1)這樣的操作未定義。右操作數是-1。 – rlbond 2009-06-26 01:46:45

3

當你右移並且最左邊的位是1時,一些平臺/編譯器將帶入0,並且一些將保留1並且使新的最左邊的位成爲1.這保留了數字的符號,所以是負數號碼保持負面並被稱爲符號擴展。

如果您嘗試((unsigned) -1) >> 1,您會看到區別,它會執行無符號的右移,因此總是會移入0位。

11

Arithmetic right shift一個移位signed number時將保留符號:

11111111 (-1) will stay 11111111 (-1) 

相反,Logical right shift將不保留符號:

11111111 (-1) will become 01111111 (127) 

您的代碼清楚地做算術移位,所以重複符號位(MSB)。操作符(>>)的功能取決於您使用的平臺的實現細節。在大多數情況下,這是一個算術轉換。

此外,請注意11111111可以有兩種不同的含義,具體取決於表示形式。這也影響到他們將被轉移的方式。

  • 如果沒有符號,11111111代表255它向右移動將不保留跡象,因爲MSB是不是一個符號位。
  • 如果有符號,11111111代表-1。在算術上將它移到右邊將保留標誌。
相關問題