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

时间:2016-08-19 08:34:23

标签: c++ c if-statement gcc arduino

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

在我的代码中我有这个:

#define DEBUG false    

...

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

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

从另一边。如果DEBUG是真的怎么办? Arduino是否测试条件或编译器只包含if的二进制文件的主体?

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

3 个答案:

答案 0 :(得分:9)

任何半好的优化编译器都会删除if语句中的整个代码,如果它可以在编译时告诉条件总是求值为false。同样,如果条件始终为真,任何半合适的编译器都会跳过检查本身。

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

#define DEBUG


#ifdef DEBUG
...
#endif

首选#ifdef的“编译器切换”语法,因为它使其他C程序员的意图更清晰。但这只是编码风格的问题 - 它将产生与原始代码相同的二进制文件。

答案 1 :(得分:1)

您编写的代码永远不应该被执行,但是,它可以在可执行文件中使用。

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

尽管如此,还有其他两种编写代码的方法,这将强制执行此代码:

  • 预处理器条件
  • constexpr if

通过使用预处理器条件,您可以在代码到达实际编译器之前删除它们。虽然它适用于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
}

答案 2 :(得分:0)

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

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

#if DEBUG == true
#endif

#ifdef DEBUG
#endif

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

第二个选项:

#define DEBUG false    

...

if (DEBUG)
{
  ...
}

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

所以我想说程序员可以更好地满足应用程序的需求。

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

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

如果您喜欢这个答案,请投票支持,我会接受 - 如果没有人提供更好的答案。