2010-08-02 61 views
5

這是非常簡單的代碼,無符號和符號比較

#include <iostream> 
using namespace std; 
int main() { 
    unsigned int u=10; 
    int i; 
    int count=0; 
    for (i=-1;i<=u;i++){ 
     count++; 
    } 
    cout<<count<<"\n"; 
    return 0; 
} 

計數的值是0,爲什麼?

+1

順便說一句,你應該使用'的std :: endl'而不是插入'\ N'成流,因爲'的std :: endl'兩者是便攜式的,確保輸出立即顯示。 – 2010-08-02 04:57:40

+1

@本:'\ n'就像便攜式;如果您現在特別想要刷新流,則只應使用'endl'。 – 2010-08-02 10:55:22

+0

'\ n'是可移植的(它被轉換爲平臺的換行順序),並且不會立即刷新流的開銷。你應該使用具有你想要的語義的那個:如果你想讓流被刷新,使用'endl',如果你只想換行,可以使用'\ n'。 – jalf 2010-09-27 23:06:18

回答

8

<=兩個操作數必須被提升到相同的類型。

很明顯,他們被提升爲unsigned int(我沒有來自我面前的標準的規則,我會在一秒鐘內看到它)。由於(unsigned int)(-1) <= u爲假,所以循環從不執行。

的規則標準,第10段,其中指出(我已經強調了在這裏也適用該規則)第5條(表達式)發現:

許多雙目操作符,預計算術操作數或枚舉類型以相似的方式導致轉換和產生結果類型。目的是產生一個共同的類型,這也是結果的類型。 這種模式如下被稱爲通常的算術轉換,其被定義爲:

  • 如果一個操作數的範圍的枚舉類型(7.2)的,不會進行任何轉換;如果另一個操作數不具有相同的類型,則該表達式不合格。
  • 如果任一操作數的類型爲long double,則另一個操作數應轉換爲long double。
  • 否則,如果其中一個操作數爲雙倍,另一個應轉換爲雙倍。
  • 否則,如果任一操作數是浮點數,則另一個操作數應轉換爲浮點數。
  • 否則,積分促銷(4.5)應在兩個操作數上執行。 60然後,下面的 規則應用於提升的操作數:
  • 如果兩個操作數具有相同類型,則不需要進一步轉換。否則,如果兩個操作數具有帶符號整數類型或兩者都具有無符號整數類型,則具有較小整數轉換等級類型的操作數應轉換爲具有較高等級的操作數的類型。
  • 否則,如果具有無符號整數類型的操作數的秩大於或等於另一操作數類型的秩,則帶符號整數類型的操作數應轉換爲無符號整數類型的操作數的類型。
  • 否則,如果具有有符號整數類型的操作數的類型可以表示具有無符號整數類型的操作數類型的所有值,則具有無符號整數類型的操作數應轉換爲帶有符號的操作數的類型整數類型。
  • 否則,兩個操作數都應轉換爲與帶符號整數類型的操作數的類型相對應的無符號整數類型。
1

它因爲-1是作爲unsigned int輸出的,所以for循環代碼永遠不會執行。

嘗試用-Wall編譯-Wextra這樣你就可以得到相應的警告(如果不是讓他們到目前爲止,並與G ++編譯)

http://en.wikipedia.org/wiki/Two's_complement

+0

謝謝,我想問你一件事我會給我的問題的鏈接,請告訴我爲什麼他們減少我的標記或他們downvote好嗎?我想擁有良好的聲譽並試圖發佈很好的問題,但他們會減少它 – 2010-08-02 04:08:45

+1

@davit:你的其他問題因爲編譯器告訴你到底發生了什麼錯誤(你錯過了一個分號),但是你在這裏沒有發佈你的問題試圖自己解決問題。 – 2010-08-02 04:20:55

4

在比較過程中(i <= u)i升級爲一個無符號的整數,並在此過程中-1轉換爲UINT_MAX。

負數的,以一個unsigned int將增加(UINT_MAX + 1)到數模轉換,所以-1變成UINT_MAX,-2變爲UINT_MAX - 1等

如果你想想看,必須將一個轉換爲另一個才能進行比較才能正常工作,並且通常編譯器會將有符號值轉換爲無符號值。在這種情況下,當然,將無符號值轉換爲帶符號的值會更有意義,但編譯器不能只根據您的意圖來決定遵循不同的規範。你應該在這裏明確地將unsigned int轉換爲signed(或者只是將它作爲一直簽名)。

+0

你的規則不起作用。實際上,2 ** 32被添加,即'UINT_MAX + 1',而不是'UINT_MAX - 1'。 – 2010-08-02 04:16:13

+0

感謝Ben,我已經改正了 - 現在改爲+。 – thomasrutter 2010-08-02 04:20:13

+1

WRT你的新評論,從signed到unsigned的轉換對於所有輸入都是明確定義的,但是從unsigned到signed的轉換可以調用實現定義的行爲(這裏不會,因爲u的值是10適合'int')。 – 2010-08-02 04:25:49

0

在一個整數以4個字節存儲的系統中,我認爲-1的值等於2147483649(1000 0000 0000 0000 0000 0000 0000 0001)的值 - 它是1,MSB設置爲1來指示這是消極的。

+1

不,在二進制補碼錶示中,'-1'被存儲爲全1。但實際的表示並不重要,因爲C++標準定義了從符號到無符號整數類型的轉換,在模塊的基本N運算中全等。 – 2010-08-02 04:18:18

+1

雖然在符號量級系統中這是事實,但現在這些情況非常罕見。大多數合理的當前系統使用2的補碼來表示整數,在這種情況下,-1將被設置爲1的所有位表示(在這種情況下,從有符號到無符號的轉換完全不需要改變數據,只改變它的方式解釋)。 – 2010-08-02 04:20:45

+1

@Jerry:符號的數量並不少見。 IEEE 754要求它。幾乎每臺計算機都使用二進制補碼整數和符號量級浮點表示。 – 2010-08-02 04:33:41

1

這是因爲i在比較之前被提升爲無符號值。這會將其設置爲值爲UINT_MAX,在32位計算機上的值等於4294967295。所以,你的循環本質上是一樣的:

// will never run 
for (i = 4294967295; i <= u; i++) { 
    count++; 
}