【问题标题】:Will A Compiler Remove An If Block That Always Evaluates to Zero?编译器会删除始终计算为零的 if 块吗?
【发布时间】:2012-02-17 22:24:42
【问题描述】:

编译器会删除这个 if 语句吗?

 #define DEBUG 0
 int main(int argc, char ** argv)
 {
    if(DEBUG)
    {
       ...
    }
    return 0;
 }

我试图用谷歌搜索这个,并搜索 stackoverflow,但我认为我的搜索词很糟糕,因为我找不到信息。

如果这是优化的,我想读什么来了解优化?

康斯坦丁

【问题讨论】:

  • 您总是可以通过要求您的编译器生成其输出的汇编列表来找出自己。
  • 取决于您的编译器及其选项,但是是的,它可能会删除整个块。如果它确实添加和删除了您需要的代码,尽管我使用 #ifdef 的条件编译而不是使用 if。
  • 这里是gcc's 选项。
  • 只要标准允许编译器执行 x 或 y,您总会发现一个编译器执行 x,而另一个编译器执行 y。所以问这种问题总是只能通过“试试看”来回答
  • 是的,我注意到不同的反应。堆栈溢出的一个好处(有点尴尬)是,当我问一个问题时,它旁边会弹出“相关”,这通常正是我正在寻找的。这种反应似乎是平常的。

标签: c++ optimization compiler-construction


【解决方案1】:

是的,任何像样的 C/C++ 编译器都会删除这样的 if 块。

【讨论】:

    【解决方案2】:

    我不确定编译器是否可以优化它。我想是的,因为在这种情况下你不会有任何副作用,所以可以在不改变代码语义的情况下安全地删除它。

    无论如何,猜测并不好,依赖优化也不好。

    为什么不使用#ifdef .. #endif 块而不是代码块?

    #define DEBUG
    
    #ifdef DEBUG
      ...
    #endif
    

    这样你会有一个确定的结果。

    【讨论】:

    • 我也在考虑这种方法,我只是不想用#ifdef 膨胀我的源文件。 (供人类阅读)。谢谢杰克。
    • 我通常只是将它们与代码一起缩进,以免视觉效果不佳..但这只是个人品味的问题
    【解决方案3】:

    您无需猜测。编译并使用调试器查看汇编指令。您甚至不需要非常熟悉汇编来查看是否为有问题的行生成了实际代码。

    【讨论】:

      【解决方案4】:

      你不能说每个编译器都会以相同的方式优化相同的东西。同样,今天可能发生的任何编译器在将来的某个版本中可能不会。

      是的,今天的一些编译器可以并且将会这样做,但这并不意味着您应该计划或期待它。如果您不想要该代码,请将其注释掉,ifdef 将其删除或删除。

      正如其他人所提到的,尝试一下并自己找出答案。如果您正在调试某些东西并怀疑这是否发生过,只需查看并找出...

      【讨论】:

      • 在这种情况下,我认为可以完全安全地假设没有工业级编译器无法优化这一点。然而另一方面,DEBUG 是一种有人可能会不小心创建一个变量,在命令行上可配置的东西。从这个意义上说,这可能很麻烦。
      • 是的,我正在与问题的更笼统的“Will A Compiler Remove”部分讨论过于开放和模糊。调试一词还会导致使用 ide 的人不知道使用了哪些命令行选项(包括优化),并且当您编译调试时会跳过一些(如果不是全部)优化,以便您可以单步执行内存监视和诸如此类的事情。
      • @dwelch,感谢您的洞察力。您能否进一步解释您的第二条评论?是在做#define DEBUG 不好的做法吗?谢谢。
      • Debug 不是我,那是 jkerian,它让我想到了为调试而编译,以便能够单步执行或观察几乎不需要优化的变量。
      【解决方案5】:

      您得到了很好的答案,可以在编译器程序集输出中检查它。我想分享一些有时对我非常有用的类似成语:

       int main(int argc, char ** argv)
       {
          const bool bDebug = false;
          if(bDebug)
          {
             ...
             LOG(""); /// some heavy loging here
          }
          return 0;
       }
      

      所以我将这样的 if-s 留在了我的代码中的一些相关位置,当我收到错误报告说发生了不好的事情时,我会逐步执行代码,当我需要输出一些大型数组/数据结构时,我会从调试器中进行修改bDebug 变量(实际上我将它们命名为 bVerbose),然后允许代码输入这样的 IF-s。您不必重新编译代码来添加繁重的日志记录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-09
        • 2013-03-14
        • 2014-03-22
        • 1970-01-01
        • 2023-03-16
        相关资源
        最近更新 更多