如何优雅地避免对这种特定类型的 for 循环发出 "condition is always true" 警告?

How to elegantly avoid "condition is always true" warning for this particular kind of for-loop?

假设我们有以下 for 循环:

#define UPPER 0U
int i;
for(i = 0; i < UPPER; i++) {
    /* foo */
}

这会产生一个W549: condition is always true警告,显然是因为我们在宏扩展后得到了for(i = 0; i < 0; i++)。在实际代码中,UPPER 是一个预编译时间参数(即由一些构建脚本根据目标平台等设置),可以取 0 到 255 之间的任何值,因此循环不是只是死代码。

UPPER == 0时如何优雅地避免这个警告?

显然,可以将 for 循环包装在 if 语句中:

#define UPPER 0U
if(UPPER != 0U) {
    int i;
    for(i = 0; i < UPPER; i++) {
        /* foo */
    }
}

但这不是我所说的优雅。

如果不想用代码包装,使用条件编译包装代码:

#if UPPER > 0
  int i;
  for(i = 0; i < UPPER; i++) {
      /* foo */
  }
#endif

优雅源于:

  • UPPER为0时无死码。
  • 完全可移植到 1970-01-01 以来的任何 C 编译器
  • 易于阅读和理解

不是很好的编码风格,但解决了任务。即使关闭优化,g++ 也会消除死代码。

#define UPPER 0U
int i;
for(i = 0; &((char*)0)[i] < &((char*)0)[UPPER]; i++) {
    /* foo */
}

它消除了 signedunsigned 比较的警告,并阻止编译器优化代码。

#define UPPER 0U
int i;
volatile int u = UPPER;
for(i=0; i < u; i++){
    /* foo */
}

使用gcc -Wall -Wextra myfile.c

测试编译