#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」。你能解釋爲什麼嗎?爲什麼輸出錯誤?
#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」。你能解釋爲什麼嗎?爲什麼輸出錯誤?
在比較signed char
得到轉換爲unsigned int
,因此看起來像一個非常大的價值。我希望編譯器能夠警告你 - 例如,「比較已簽名和未簽名的東西是令人困惑的」。
這種轉換是根據「關係運算符」規定:
如果兩個操作數的算術具有類型,通常的 算術轉換被執行。
作爲比較,如果一個操作數是無符號的,則另一個操作數如果其類型被簽名,則隱式轉換爲無符號!
更多地在這裏找到:Signed/unsigned comparisons
在你的情況有符號的字符轉換爲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類型。
C11§6.8AL3 P95:
如果兩個操作數的算術具有類型,通常的算術轉換爲執行 。
C11§6.3.1.8AL1的p53:
[...]如果具有無符號整數類型操作數的秩大於或 等於所述其他的類型的秩操作數,那麼帶有符號整數類型的操作數 將轉換爲具有無符號整數類型的 操作數的類型。
所以y
將促進爲無符號類型,並且將大於x
(1
)。
獲取用於所有的警告,即在GCC的情況下進行編譯:
gcc -Wall -Wextra -pedantic source.c -o prog
在你的情況-Wextra
提供以下信息標誌:
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
這並不能解釋爲什麼,但至少會警告你;)。
解釋是,與關係運算符相比,評估爲-1
的帶符號變量等於無符號評估值UINT_MAX
。
編譯器必須做在這種情況下,明確的東西,這就是人們想出了...
當編譯器看到有符號整數它促進符號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
問候。
對不起,編譯器不警告。它只是給出了提到的輸出。我正在使用Codeblocks編譯器。謝謝您的回答。 – Niteesh 2012-07-29 12:34:44