2014-11-14 110 views
0

此警告不應出現在此代碼中嗎?「帶符號和無符號整數表達式之間的比較」只帶有無符號整數

#include <stdio.h> 

int main(void) { 

    unsigned char x = 5; 
    unsigned char y = 4; 
    unsigned int z = 3; 

    puts((z >= x - y) ? "A" : "B"); 

    return 0; 

} 

z是一個不同的大小,但它是相同的簽名。有沒有我不知道的整數轉換?下面是GCC輸出:

$ gcc -o test test.c -Wsign-compare 
test.c: In function ‘main’: 
test.c:10:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] 
    puts((z >= x - y) ? "A" : "B"); 
     ^
$ gcc --version 
gcc (Debian 4.9.1-15) 4.9.1 

如果z是一個unsigned char我不明白的錯誤。

+0

適合我!不要得到一個錯誤或警告 – Rizier123 2014-11-14 14:51:26

+0

http://stackoverflow.com/questions/17312545/type-conversion-unsigned-to-signed-int-char – Lundin 2014-11-14 15:02:43

+0

@ Rizier123:我一直使用C多年沒有這個警告,這就是爲什麼我甚至不需要知道這一點。我猜gcc直到最近才發出這個警告,所以也許你的gcc版本是不同的? – 2014-11-14 15:16:27

回答

3

問題是加法運算符對算術類型執行通常的算術轉換。在這種情況下,它會導致在操作數上執行整數提升,這會導致unsigned char被轉換爲int,因爲signed int可以表示所有unsigned char類型的值。

相關線程Why must a short be converted to an int before arithmetic operations in C and C++?解釋了促銷的理由。

+0

我明白了,謝謝,所以可以表示爲int的整數被提升爲int。這實際上是因爲這個警告而令人討厭的。要麼我把整數改爲'int',即使它們總是正面的,我使用了一個強制類型,或者我禁用了這個警告。任何想法什麼是最好的解決方案? – 2014-11-14 15:12:35

+0

@MatthewMitchell使用強制轉換是明確的,而禁用警告可以稍後隱藏可能的問題。 – 2014-11-14 15:20:19

+0

當然,鑄造會使代碼複雜化。使用'int'代替'unsigned char'和'unsigned short'會更好嗎? – 2014-11-14 15:26:34

1

C有這個概念稱爲「整數推廣」。

基本上這意味着所有數學都在signed int中完成,除非您確實堅持否則,或者它不適合。

如果我把在隱式轉換,你的榜樣其實內容是這樣的:

puts((z >= (int)x - (int)y) ? "A" : "B"); 

所以,現在你看到的符號/無符號不匹配。

不幸的是,您無法安全地單獨使用強制轉換來解決此問題。有幾個選項:

puts((z >= (unsigned int)(x - y)) ? "A" : "B"); 

puts((z >= (unsigned int)x - (unsigned int)y) ? "A" : "B"); 

puts(((int)z >= x - y) ? "A" : "B"); 

但他們都來自同一個問題的困擾:如果yx大,如果z大於INTMAX(不是它會在示例中)?

一個正確正確的解決方案可能是這樣的:

puts((y > x || z >= (unsigned)(x - y)) ? "A" : "B") 

最後,除非你真的需要額外位時,通常最好避免無符號整數。

+0

更準確地說:所有小整數類型隱式整數提升爲「int」。用於操作的類型取決於整數提升和平衡(「常用算術轉換」)。 – Lundin 2014-11-14 15:06:50

+0

我確實說過「基本上」。 – ams 2014-11-14 15:36:00

相關問題