“带符号和无符号整数表达式之间的比较”只带有无符号整数
此警告不应出现在此代码中吗?“带符号和无符号整数表达式之间的比较”只带有无符号整数
#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
我不明白的错误。
问题是加法运算符对算术类型执行通常的算术转换。在这种情况下,它会导致在操作数上执行整数提升,这会导致unsigned char被转换为int,因为signed int可以表示所有unsigned char类型的值。
相关线程Why must a short be converted to an int before arithmetic operations in C and C++?解释了促销的理由。
我明白了,谢谢,所以可以表示为int的整数被提升为int。这实际上是因为这个警告而令人讨厌的。要么我把整数改为'int',即使它们总是正面的,我使用了一个强制类型,或者我禁用了这个警告。任何想法什么是最好的解决方案? – 2014-11-14 15:12:35
@MatthewMitchell使用强制转换是明确的,而禁用警告可以稍后隐藏可能的问题。 – 2014-11-14 15:20:19
当然,铸造会使代码复杂化。使用'int'代替'unsigned char'和'unsigned short'会更好吗? – 2014-11-14 15:26:34
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");
但他们都来自同一个问题的困扰:如果y
比x
大,如果z
大于INTMAX
(不是它会在示例中)?
一个正确正确的解决方案可能是这样的:
puts((y > x || z >= (unsigned)(x - y)) ? "A" : "B")
最后,除非你真的需要额外位时,通常最好避免无符号整数。
适合我!不要得到一个错误或警告 – Rizier123 2014-11-14 14:51:26
http://stackoverflow.com/questions/17312545/type-conversion-unsigned-to-signed-int-char – Lundin 2014-11-14 15:02:43
@ Rizier123:我一直使用C多年没有这个警告,这就是为什么我甚至不需要知道这一点。我猜gcc直到最近才发出这个警告,所以也许你的gcc版本是不同的? – 2014-11-14 15:16:27