2012-07-29 118 views
1
#include<stdio.h> 

main() 
{ 
     unsigned x=1; 
     signed char y=-1; 
     clrscr(); 
     if(x>y) 
     printf("x>y"); 
     else 
    printf("x<=y"); 
} 

有符號字符的值從-128增加到127.所以預期輸出應該是'x> y',但它不是。編譯器給出輸出 - 「x < = y」。你能解釋爲什麼嗎?爲什麼輸出錯誤?

回答

7

在比較signed char得到轉換爲unsigned int,因此看起來像一個非常大的價值。我希望編譯器能夠警告你 - 例如,「比較已簽名和未簽名的東西是令人困惑的」。

這種轉換是根據「關係運算符」規定:

如果兩個操作數的算術具有類型,通常的 算術轉換被執行。

+0

對不起,編譯器不警告。它只是給出了提到的輸出。我正在使用Codeblocks編譯器。謝謝您的回答。 – Niteesh 2012-07-29 12:34:44

0

作爲比較,如果一個操作數是無符號的,則另一個操作數如果其類型被簽名,則隱式轉換爲無符號!

更多地在這裏找到:Signed/unsigned comparisons

0

在你的情況有符號的字符轉換爲unsigned int類型,所以我們得到一個大的正整數,而不是-1。這裏是ANSI C標準草案的一個摘錄,它解釋了在發生常規算術轉換期間發生的事情。

3.2.1.5常見的算術轉換

許多雙目操作符,期待 轉化和產量的結果類型以類似的方式的算術類型原因操作數。目的是產生一個通用的類型,這也是結果的類型,即 。這種 模式被稱爲通常的算術轉換:首先,如果任一 操作數的類型爲long double,則另一個操作數轉換爲長整數 double。否則,如果任一操作數的類型爲double,則另一個操作數將轉換爲double。否則,如果任一操作數的類型爲 float,則另一個操作數轉換爲float。否則, 積分促銷在兩個操作數上執行。然後 應用下列規則:如果任一操作數的類型無符號長 int,則另一個操作數轉換爲unsigned long int類型。否則,如果 一個操作數的類型長int和另一個具有unsigned int類型, 如果一個長整型可以表示一個unsigned int的所有值,操作數 類型的無符號整型轉換爲長整型;如果long int不能 表示無符號整型的所有值,則兩個操作數都是 轉換爲unsigned long int。否則,如果任一操作數的類型爲 long int,則另一個操作數將轉換爲long int。 否則,如果任一操作數的類型爲unsigned int,則另一個操作數轉換爲unsigned int。否則,兩個操作數都有 int類型。

2

C11§6.8AL3 P95:

如果兩個操作數的算術具有類型,通常的算術轉換爲執行 。

C11§6.3.1.8AL1的p53:

[...]如果具有無符號整數類型操作數的秩大於或 等於所述其他的類型的秩操作數,那麼帶有符號整數類型的操作數 將轉換爲具有無符號整數類型的 操作數的類型。

所以y將促進爲無符號類型,並且將大於x1)。

0

獲取用於所有的警告,即在GCC的情況下進行編譯:

gcc -Wall -Wextra -pedantic source.c -o prog 

在你的情況-Wextra提供以下信息標誌:

warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 

這並不能解釋爲什麼,但至少會警告你;)。

解釋是,與關係運算符相比,評估爲-1的帶符號變量等於無符號評估值UINT_MAX

編譯器必須做在這種情況下,明確的東西,這就是人們想出了...

0

當編譯器看到有符號整數它促進符號int無符號比較一個unsigned int,這意味着要添加這個(在Linux機器)已簽署的一個:

#define UINT_MAX (~0U) (defined in this header file : /include/linux/kernel.h) 

所以,現在你是比較UINT_MAX - 與X,這清楚地解釋輸出1(UINT_MAX + Y)

編輯:更加清楚:在32位機器--->UINT_MAX = 2 147 483 648 = 2**31

問候。