6

我有一个小样本功能:

#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 比较。为什么它声称比较总是正确的?

4

4 回答 4

12

即使使用演员表,在所有已定义行为的情况下,比较仍然是正确的。编译器仍然确定它(signed int)0的值为 0,并且如果您的程序已定义行为(如果值超出有符号类型的范围,则从无符号转换为有符号是未定义的)仍然确定它(signed int)x)是非负数。

所以编译器继续警告,因为它继续完全消除 else 情况。

编辑:要使警告静音,请将代码编写为

#define VALUE 0

int test(unsigned char x) {
#if VALUE==0
  return 1;
#else
  return x>=VALUE;
#endif
}
于 2009-09-01T13:19:45.323 回答
7

x是 an unsigned char,表示它介于 0 和 256 之间。由于 anint大于 a char,因此转换unsigned char为ssigned int仍保留chars 原始值。由于此值始终 >= 0,因此您if的值始终为 true。

于 2009-09-01T13:21:13.887 回答
3

an 的所有值都unsigned char可以完美地保存在您的 中int,因此即使使用演员表,您也永远不会得到负值。您需要的演员是signed char- 但是,在这种情况下,您应该在函数签名中x声明。signed向客户撒谎说您需要一个未签名的值是没有意义的,而实际上您需要一个签名的值。

于 2009-09-01T13:22:31.730 回答
1

的to意味着您的功能简化为#defineVALUE0

int test(unsigned char x) {
  if (x>=0)
    return 0;
  else
    return 1;
}

由于x始终作为 a 传入,因此无论您是在语句中转换还是转换为 a unsigned char,它都将始终具有介于0和之间的值。因此,编译器会警告您将始终大于或等于,并且永远无法到达该子句。255x0signed intifx0else

于 2009-09-01T13:19:24.607 回答