C 比较 'x < 0' 其中 'x' 的类型是任意的,即可能是无符号的

C comparison 'x < 0' where type of 'x' is arbitrary, i.e. might be unsigned

给定:

定义为TheValueT的类型,可以任意配置,例如如 uint8_tint64_。让有一些代码:

TheValueT   x = ...;

... do something to 'x' ...

if( x < 0 ) {
   /* Do something. */
}

问题:

碰巧如果TheValueT被定义为无符号类型,编译器会报错'condition always true because of limited range of type ...'。

问题:

如何在让TheValueT仍然是任意整数类型的同时避免编译器警告?该解决方案应该适用于最广泛的 C 编译器。

也许是通用解决方案?

#include <stdio.h>
#include <stdlib.h>

#define less_than_zero(x) _Generic((x) + 0, \
  int: (x) < 0, \
  long: (x) < 0, \
  long long: (x) < 0, \
  default: (x) * 0 \
  )

#if 1
int main(void) {
  short sh = -1;
  int i = -1;
  long long ll = -1;
  unsigned short us = -1u;
  unsigned u = -1u;
  unsigned long long ull = -1u;

  if (less_than_zero(sh)) puts("sh");
  if (less_than_zero(i)) puts("i");
  if (less_than_zero(ll)) puts("ll");
  if (less_than_zero(us)) puts("us");
  if (less_than_zero(u)) puts("u");
  if (less_than_zero(ull)) puts("ull");
  return 0;
}

条件总是为真,因为类型警告的范围有限。
输出

sh
i
ll

编写测试的一种简单而安全的方法是:

TheValueT x = /* ... */;

if (x < 1 && x != 0) {
    // do something
}

足够聪明的编译器可能无论如何都会对此发出警告,但是对于可以编写为涵盖所有可能的整数类型(包括扩展类型)的任何正确替代方案也是如此。 确实解决了我实施中的警告。

没有其他方法需要涉及 x 的值的算术计算在所有情况下都明确地产生正确的结果——这些 运行 成为 x 的极端值的问题它或其他类型的范围。

这确实假定 TheTypeT 必须是 整数 类型。如果浮动类型也是可能的,那么您最好的选择可能是接受警告,或者使用编译器标志在生产构建期间关闭该特定警告。

theme 的变体。也适用于 FP。

if (x <= 0 && x != 0) {