unsigned int a; unsigned char b,c; void test(void) { if (a < b) return; if (a < (b ? b : c)) return; }
当我编译它(使用Microsoft cl,来自MS SDK 7,-W3警告级别)时,第二次比较会发出警告:C4018,签名/无符号不匹配.第一次比较没有发出警告.
我已经检查了MS docs on the conditional operator并且他们说如果两个操作数是相同的类型,结果将是相同的类型,所以它应该作为第一个比较.我错过了什么吗?
UPD:用gcc -Wall -Wextra -pedantic进行测试,没有任何警告.
解决方法
结果是int还是unsigned int不会(直接)依赖于原始类型的签名,但是它的范围:int甚至用于无符号类型,只要可以表示所有值,这就是unsigned char的情况.在主流架构上.
其次,由于两个操作数最终具有相同的转换等级,但是一个是无符号的,另一个操作数也将转换为无符号类型.
在语义上,您的表达式读取
a < (unsigned int)(int)b
和
a < (unsigned int)(b ? (int)b : (int)c)
编译器显然足够聪明,可以注意到第一种情况不会导致问题,但第二种情况则失败.
Steve Jessop的评论很好地解释了这可能发生的原因:
I would imagine that in the first case the compiler thinks,“I have a comparison operator whose operand types are
unsigned int
andunsigned char
. No need for a warning,now let’s apply promotion followed by usual conversion”.In the second case it thinks,“I have a comparison operator whose operand types are
unsigned int
andint
(which I derived as the type of the conditional expression on the RHS). Best warn about that!”.