【问题标题】:Clang/GCC disable unused code warning as a result of conditional macro由于条件宏,Clang/GCC 禁用未使用的代码警告
【发布时间】:2017-08-09 18:24:12
【问题描述】:

我正在编写一个包含调试代码的程序,该代码可以通过宏 DEBUG 禁用。设置为1时,调试代码应该编译成二进制,设置为0时,调试代码不应该。

我在启用 -Wunreachable-code 的情况下进行编译,而我的问题来自编译如下代码:

if (DEBUG) {
    printf("debug string!\n");
}

启用调试后,这将编译正常,因为条件将始终评估为 1 (true)。但是,当禁用调试 (DEBUG=0) 时,我在第二行的 printf 调用中收到无法访问的代码警告。我知道这可以通过#ifdef/#endif 预处理器指令来解决,但是如果可以避免的话,我不喜欢用预处理器指令填充我的程序主体。

我想知道是否有任何方法可以在不使用诊断编译指示 (#pragma GCC diagnostic) 的情况下将我的代码保留为 c 风格的条件。任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 除非您使用的是旧编译器,否则您不应该因为这样做而收到任何无法访问的警告(大约 3 年前,-Wunreachable-code 也已从 gcc 中删除,该标志只是被默默接受,但确实什么都没有)
  • 您需要注意您的 clang 版本和您使用的编译器标志。至少某些 clang 版本(例如,Debian 伸展中的 clang 3.8)不会针对具有常量来自宏的常量条件的 if 语句发出警告。
  • 您是否考虑过放弃 if 语句并使用调试语句?见stackoverflow.com/questions/1941307/c-debug-print-macros

标签: c gcc


【解决方案1】:

您可以使用前置处理器条件而不是运行时条件:

#if DEBUG == 1
  printf("debug string!\n");
#endif

因此,完整的调试代码被“消除”而不留下“空”代码块。这比让任何调试代码干净得多,因为调试代码在变化的条件下可能会表现不同并影响生产中的其余代码。

或者,如果由于某种原因您不能使用预处理器条件,您可以引入 log- 或 trace- 函数,通常在单独的翻译单元中。然后你可以对其中的DEBUEG-state 做出反应。您甚至可以提供两个库实现,一个用于生产的“空”实现,一个用于调试的“工作”实现,并配置您的构建以选择正确的实现。

但是——如上所述——即使是“空”函数的调用也会影响编译时优化或运行时行为。所以我真的建议采用预处理器的方式。

【讨论】:

    【解决方案2】:

    我只收到关于 clang 的警告(如果 -Wunreachable-code 已打开),而不是 gcc。 开关使警告静音。或者,pragma 也可以(如果您只反对 pragma 指令,则可以使用 _Pragma 关键字)。

    #include <stdio.h>
    #define DEBUG 0
    int main()
    {
    #if 1
        switch(!!DEBUG){
        case 1: puts("hello world");
        case 0:;
        }
    #else
        _Pragma("gcc diagnostic push(\"-Wno-unreachable_code\")")
        if(DEBUG){
            puts("hello world");
        }
        _Pragma("gcc diagnostic pop")
    #endif
    
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-21
      • 2022-09-23
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 2011-03-23
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多