编译器:如果条件永远是真/假,该怎么办?

我考虑条件和编译器。 我正在为Arduino编写应用程序,因此我需要应用程序尽可能快。

在我的代码中,我有这样的:

#define DEBUG false    

...

if (DEBUG)
{
  String pinName;
  pinName = "Pin ";
  pinName += pin;
  pinName += " initialized";
  Serial.println(pinName);
}

我想知道如果编译器不包含二进制文件中的代码(代码在if块)。 条件总是错误的,所以程序永远不会去那里。

从另一面。 如果DEBUG是真的呢? Arduino测试条件还是编译器仅包含二进制文件中的if?body?

我发现这个网站https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_4.html关于#if指令,所以我可以重写代码以使这些指令代替“正常”。 但是我想知道是否应该重写它,或者是否浪费时间。


如果它在编译时可以告诉条件总是计算为false,那么任何half-decent优化编译器都会删除if语句中的所有代码。 同样,如果条件始终为真,任何半象限编译器都会跳过检查本身。

事实上,这完全等同于“编译器开关”,例如:

#define DEBUG


#ifdef DEBUG
...
#endif

#ifdef的“编译器开关”语法更喜欢,因为它使得其他C程序员的意图更清晰。 但这只是编码风格的问题 - 它会导致与原始代码相同的二进制文件。


您编写的代码不应该执行,但是,它可能在可执行文件中可用。

我会说,当你禁用优化时(例如将-O0添加到Clang和GCC),编译器将需要保留此代码。 在所有其他情况下,我希望编译器将删除代码,因为这是一个非常简单的优化,具有显着的代码大小效果。 例如,GCC在-O和更高处消除这个问题。 (见手册)

尽管如此,还有另外两种编写代码的方式,它们将强制执行以下代码,使其不被包含:

  • 预处理器条件
  • constexpr如果
  • 通过使用预处理器条件,您将能够在代码到达实际编译器之前将其删除。 它可能对你的缩进有点侵入性,尽管它可以用于C和C ++标准的所有编译器和版本。

    #ifdef DEBUG
       { // Optional: Adding extra scope to prevent usage of local variables after the endif
       // Code to eliminate
       }
    #endif
    

    但是,如果您使用的是C ++ 17,那么也可以使用constexpr if。 这在代码中会更少干扰,虽然if语句中的代码必须是句法正确的,但它不必编译(所以语义上不正确)。

    这可以写成:

    if constexpr (DEBUG)
    {
        // Code to eliminate
    }
    

    我不喜欢回答我自己的问题,因为如果没有你的帮助,我不会想出来,伙计们。

    无论如何,第一个选择是使用:

    #if DEBUG == true
    #endif
    

    要么

    #ifdef DEBUG
    #endif
    

    编译器不会在#if / #ifdef中获得代码(预处理器将其删除),所以如果这部分代码有问题,如果DEBUG设置为false或根本没有定义,则没有人会知道它(谢谢@Klaus)。

    第二种选择:

    #define DEBUG false    
    
    ...
    
    if (DEBUG)
    {
      ...
    }
    

    如果条件为false,任何较新的编译器都应该删除'if'块,或者如果条件为真,则删除'if'语句并离开body。

    所以我会说这是程序员对套件更好的应用需求。

    如果您需要确保代码不会包含在二进制文件中,第一种方法会更好。

    如果您希望编译器在您每次编译程序时检查整个代码,第二种方法会更好。

    如果你喜欢这个答案,为它投票,我会接受它 - 如果没有人提供更好的答案。

    链接地址: http://www.djcxy.com/p/79915.html

    上一篇: Compiler: What if condition is always true / false

    下一篇: MSVCRT system function return code is always