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



给定:

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

TheValueT   x = ...;
... do something to 'x' ...
if( x < 0 ) {
   /* Do something. */
}

问题:

碰巧的是,如果TheValueT被定义为无符号类型,编译器会抱怨"条件总是为真,因为类型范围有限......"。

问题:

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

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

TheValueT x = /* ... */;
if (x < 1 && x != 0) {
    // do something
}

无论如何,足够聪明的编译器可能会警告这一点,但是对于可以编写以涵盖所有可能的整数类型(包括扩展类型(的任何正确替代方法也是如此。 这确实可以解决我的实现中的警告。

没有其他需要涉及定义值的算术计算的替代方案x在所有情况下都能产生正确的结果 - 这些都会遇到x值在其或其他类型范围的极端值的问题。

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

也许是一个通用解决方案?

#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

主题的变体。也适用于FP。

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

最新更新