繁体   English   中英

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

[英]Compiler: What if condition is always true / false

我想到条件和编译器。 我正在编写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指令,所以我可以重写代码以获得这些指令而不是“正常”if。 但我想知道我是否应该重写它,或者是否浪费时间。

任何半好的优化编译器都会删除if语句中的整个代码,如果它可以在编译时告诉条件总是求值为false。 类似地,如果条件总是为真,那么任何半正式编译器都会跳过检查本身。

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

#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。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM