【问题标题】:How to elegantly fix this unused variable warning?如何优雅地修复这个未使用的变量警告?
【发布时间】:2016-09-21 13:30:34
【问题描述】:

我正在编写一些 C 代码,当设置了 DEBUG 标志时会执行大量错误报告和日志记录,当使用 DEBUG 标志不进行编译时,有时会产生 unused variable 警告设置。

#ifdef DEBUG
#define CHECK(expr) foo(expr)
#else
#define CHECK(expr)
#endif /* DEBUG */

int x = bar(a, b, c); /* bar has to be called for both DEBUG begin defined and undefined */ 
CHECK(x == SOME_VALUE); /* Produces an "unused variable" warning if DEBUG is undefined

编辑:稍微提醒一下(不确定是否有任何后果):CHECK 宏的参数是一个表达式,而不是单个变量

对于这种模式,摆脱未使用变量警告的最佳方法是什么?

我尝试过/虽然:

#ifdef DEBUG
int x = bar(a, b, c);
#else
bar(a, b, c);
#endif
CHECK(x == SOME_VALUE);

然后,为了避免将调用写入bar(在实际调用中更复杂):

#ifdef DEBUG
int x = 
#endif
bar(a, b, c);
CHECK(x == SOME_VALUE);

但是,我觉得这不是一个干净易读的解决方案。有没有更好的办法?请注意,出于性能原因,如果 DEBUG 未定义,CHECK(expr) 宏不应生成任何代码(编辑:,因此不应评估 expr)。

有没有比我上面概述的更优雅的方法?

【问题讨论】:

  • @yuhao 删除compiler-warning标签有什么具体原因吗?
  • 也许你应该说:“CHECK(expr) 宏不应产生任何代码,但仍应评估 expr,换句话说,CHECK(bar(a,b,c) == someval) 必须导致 bar(a,b,c) 被调用。
  • @shodanex:我为什么要这样做?如果 DEBUG 未定义,则不应计算表达式 expr
  • @mort,我的意思是你应该定义是否要评估 expr。
  • @shodanex:为了清楚起见,我对其进行了编辑,尽管我认为它实际上暗示了“如果 DEBUG 未定义,宏不应生成任何代码”

标签: c macros unused-variables


【解决方案1】:
#ifdef DEBUG
    #define CHECK(x) x
#else
    #define CHECK(x) ((void)sizeof((void)(x),0))
#endif

我认为这解决了所有可能的问题:

  • sizeof 确保表达式根本不被计算,因此它的副作用不会发生。这与仅调试构造的通常行为一致,例如assert
  • ((x), 0) 使用逗号运算符吞下(x) 的实际类型。 This is to prevent VLAs from triggering evaluation
  • (void) 明确忽略 (x)sizeof 的结果,因此不会出现“未使用值”警告。

【讨论】:

  • 虽然这确实有效,但它并不比我在问题中的解决方案更优雅......
  • @mort 你是什么意思?你的代码没有#ifdefs,在发布模式下根本不生成代码。我不认为它会变得更好。
  • 但是如果你想要副作用?这里 CHECK(bar(a,b,c) == SOME_VALUE) 在非调试模式下根本不会生成代码。
  • @Quentin:是的,但非专家不会立即理解 CHECK 宏的作用以及为什么需要使用 sizeof
  • @shodanex 如果您想要副作用,请使用 Sourav 的答案。但这与 OP 的“发布模式下无代码”要求相冲突。郑重声明,assert 也是这样做的。
【解决方案2】:

如果我正确理解了你的问题,你可以这样做

#ifdef DEBUG
.
.
#else
#define CHECK(expr) ((void)(expr))
#endif /* DEBUG */

摆脱警告。

【讨论】:

  • @Rémi This shows the warningthis does not。你能告诉我别的吗?
  • 嗯..有人支持@remi 的评论,你们也可以给我看一些代码吗?还是回答上的 DV 和评论上的 UV 是由于 PEBKAC 造成的?
  • 警告:虽然这解决了警告,但即使在发布模式下,它也会执行表达式(以及所有副作用),而原始宏没有这样做。
  • @SouravGhosh:代码很好,而且是正确的理念——基本上。它只是在expr 周围缺少一对括号。照原样,它可能会为 CHECK(x) 调用“语句中未使用的表达式”或类似警告。
  • @Quentin:你对副作用的看法是对的。但是由于调试模式不应以其他方式表现,因此此类影响应仅限于错误统计信息 - 对正常代码没有影响。这可以通过为释放目标为空/未调用的辅助函数来实现。最后:没有副作用的死表达式会被好的编译器优化掉。
【解决方案3】:

有了这个解决方案,就不需要中间变量了。

#define DEBUG

#define DOCHECK(a) printf("DOCHECK %d\n", a)

#ifndef DEBUG
#define CHECK(a, b) a
#else
#define CHECK(a, b) do {int x = a; DOCHECK(x == b);} while (0)
#endif

int bar(int x, int y)
{
  return x+y;
}    

int main()
{
  CHECK(bar(2,3), 2+3);
  return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 2020-02-29
    • 2016-06-20
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    相关资源
    最近更新 更多