我有一个小样本函数:
#define VALUE 0
int test(unsigned char x) {
if (x>=VALUE)
return 0;
else
return 1;
}
我的编译器警告我,比较(x> = VALUE)在所有情况下都是正确的,这是正确的,因为x是无符号字符,VALUE定义为值0.所以我将代码更改为:
if ( ((signed int) x ) >= ((signed int) VALUE ))
但警告又来了。我测试了三个GCC版本(所有版本> 4.0,有时你必须启用-Wextra)。
在更改的情况下,我有这个显式的强制转换,它应该是一个有符号的int比较。为什么声称这种比较总是正确的呢?
答案 0 :(得分:12)
即使使用强制转换,在所有已定义行为的情况下仍然可以进行比较。编译器仍然确定(signed int)0
的值为0,并且如果您的程序已定义行为,仍然确定(signed int)x)
是非负的(如果值超出范围,则从unsigned转换为signed是未定义的签名类型)。
因此,编译器会继续发出警告,因为它会继续完全消除其他情况。
修改:要使警告静音,请将代码编写为
#define VALUE 0
int test(unsigned char x) {
#if VALUE==0
return 1;
#else
return x>=VALUE;
#endif
}
答案 1 :(得分:7)
x
是unsigned char
,这意味着它介于0到256之间。由于int
大于char
,因此将unsigned char
转换为{{} 1}}仍保留signed int
的原始值。由于此值始终>> = 0,因此char
始终为真。
答案 2 :(得分:3)
unsigned char
的所有值都可以在int
中完美展现,因此即使使用演员,你也永远不会得到负值。您需要的投射是signed char
- 但是,在这种情况下,您应该在函数签名中将x
声明为signed
。没有必要向客户说明你需要一个无符号值,而实际上你需要一个签名值。
答案 3 :(得分:1)
#define
VALUE
到0
表示您的功能已降至此:
int test(unsigned char x) {
if (x>=0)
return 0;
else
return 1;
}
由于x
始终作为unsigned char
传递,因此无论您是否{{1},它都将始终具有0
和255
之间的值。 {}}或x
到0
语句中的signed int
。因此,编译器警告您if
将始终大于或等于x
,并且永远不会达到0
子句。