2010-07-08 87 views
4

如果我有int temp =(1 < < 31)>> 31。溫度怎麼會變成-1? 我該如何解決這個問題? 謝謝按位移問題

回答

9

默認情況下,Ints是帶符號的,這通常意味着高位被保留以指示整數是否爲負值。請查閱Two's complement以瞭解其工作原理的解釋。

這裏的結果是:

[[email protected]:~]% cat test.c 
#include <stdint.h> 
#include <stdio.h> 

int main(int argc, char **argv[]) { 
    uint32_t uint; 
    int32_t sint; 
    int64_t slong; 
    uint = (((uint32_t)1)<<31) >> 31; 
    sint = (1<<31) >> 31; 
    slong = (1L << 31) >> 31; 
    printf("signed 32 = %d, unsigned 32 = %u, signed 64 = %ld\n", sint, uint, slong); 
} 

[[email protected]:~]% ./test 
signed 32 = -1, unsigned 32 = 1, signed 64 = 1 

注意如何可以通過使用一個「無符號」 INT(允許使用所有32位的)來避免這種問題,或者去一個更大的類型,你不要沒有溢出。

+0

特別要小心,有符號值的右移是編譯器依賴的。所以在這裏看到的輸出只適用於特定平臺,其他平臺可能會給出其他結果。 – 2010-07-08 18:46:15

+0

確實如此,但這並不會使使用無符號或更長變量的修復無效。我認爲。 – 2010-07-08 19:09:55

1

int被簽名。

什麼'問題' - 你想做什麼?

int i = (1<<31); // i = -2147483648 
i>>31; // i = -1 

unsigned int i = (1<<31); // i = 2147483648 
i>>31; // i = 1 

PS ch是一個不錯的命令行「C」 intepreter窗戶,讓你嘗試這種東西無需編譯,它也給你一個UNIX命令shell。請參閱http://www.drdobbs.com/184402054

5

對於您的情況,表達式中的1是一種帶符號的類型 - 所以當您將它升檔31時,其符號會發生變化。然後降檔導致符號位被複制,並且最終得到一個0xffffffff的位模式。

你能解決這個問題是這樣的:

int temp = (1UL << 31) >> 31; 

GCC發出警告這樣那樣的錯誤,如果你已經-Wall開啓。

+0

我檢查了符號擴展的描述,但是我看不到它與OP觀察到的現象有何關係。問題是,在他的實現中,右移是算術移位,int是有符號的,長32位。 http://en.wikipedia.org/wiki/Arithmetic_shift – 2010-07-08 17:57:38

+0

@Maciej,看起來你是對的 - 我在這裏濫用這個詞。我會編輯以澄清這一點。 – 2010-07-08 18:02:13

1

當你做(1<<31),符號位的MSB被設置(變爲1)。然後,當你做正確的轉變時,它是符號擴展。因此,你得到-1。解決方案:(1UL < < 31)>> 31.

+0

糟糕,Carl已經回答了。 – 341008 2010-07-08 17:55:54

0

位表示在對整數變量執行「such」左移時設置的符號。因此,結果。