2016-01-31 74 views
0

這裏是我的代碼:是無符號long int對此操作是否正確?

#include <stdio.h> 

int main(int argc, char *argv[]) { 

    unsigned long int x = 0; 

    // trying to make x = 2,147,483,648 
    x = 1 << 31; 

    printf("%lu", x); 
} 

它返回得到x = 18446744071562067968.我讀了unsigned long int類型應該上升到4,294,967,296,那麼爲什麼我不能用1 < < 32到集合X等於2,147,483,648?

+0

無論寫在哪裏:這是錯的! http://port70.net/~nsz/c/c11/n1570.html#5.2.4.2.1並獲得正確的數學。提示:最大。價值不可能是平等的。 – Olaf

+0

胡?它表示無符號長整型對象的最大值int ULONG_MAX 4294967295 // 2^32 - 1 – Austin

+0

在受歡迎的請求中,我嘗試幫助您一點。 C標準的公佈鏈接中第1段的最後一句陳述「其實現定義的值應與所示的相同符號在數量(絕對值)上等於或大於**」。希望重點有所幫助。另外請注意,您在代碼中用「31」代替,而在文本中用「32」代替。非常重視「一次計數」;這隻會使值增加一倍,導致windows'unsigned long'的未定義行爲。對於POSIX來說,它是正確的,順便說一句。因爲它有64位。 – Olaf

回答

3

1 << 31導致未定義的行爲,如果您的系統具有32位整數。字面1是一個有符號整數。

你需要做一個無符號的轉變,而不是簽署的轉變:

x = 1UL << 31; 

我添加L使代碼仍然是正確的,即使在16位系統,並且它不會傷害做所以。


非正式地,將1轉換爲符號位是未定義的。正式文本可以在C11標準的部分6.5.7/4中找到:

E1 << E2結果是E1左移E2位位置;空位填充零。 [...]如果E1具有帶符號類型和非負值,並且E1×2E2可以在結果類型中表示,那麼這就是結果值;否則,行爲是不確定的。


您的其他問題,「爲什麼我不能用1 << 32」是由相同的報價覆蓋。那麼1UL << 32?如果系統發生32位unsigned long那麼這也將根據6.5.7/3未定義:

[...]如果右操作數的值是負的或大於或等於所述提升的左操作數的寬度,行爲是未定義的

但它會工作,如果您的系統有64位unsigned long。爲了避免在不同系統上編譯代碼時出現中斷(此目標被稱爲代碼可移植性),您可以編寫(uint64_t)1 << 32(或1ULL << 32),該代碼保證可以正常工作。

相關問題