我考虑条件和编译器。我正在为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"如果。但我想知道我是否应该重写它,或者是否浪费时间。
答案 0 :(得分:9)
任何半好的优化编译器都会删除if语句中的整个代码,如果它可以在编译时告诉条件总是求值为false。同样,如果条件始终为真,任何半合适的编译器都会跳过检查本身。
实际上这完全等同于“编译器开关”,例如:
#define DEBUG
#ifdef DEBUG
...
#endif
首选#ifdef
的“编译器切换”语法,因为它使其他C程序员的意图更清晰。但这只是编码风格的问题 - 它将产生与原始代码相同的二进制文件。
答案 1 :(得分:1)
您编写的代码永远不应该被执行,但是,它可以在可执行文件中使用。
我想说当你要禁用优化时(例如将-O0
添加到Clang和GCC),编译器将需要保留此代码。
在所有其他情况下,我希望编译器将删除代码,因为这是一个非常简单的优化,具有显着的代码大小效果。例如,GCC在-O
及更高版本中消除了这一点。 (见manual)
尽管如此,还有其他两种编写代码的方法,这将强制执行此代码:
通过使用预处理器条件,您可以在代码到达实际编译器之前删除它们。虽然它适用于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。
所以我想说程序员可以更好地满足应用程序的需求。
如果您需要确保代码不会包含在二进制文件中,第一种方法会更好。
如果希望编译器在每次编译程序时检查整个代码,第二种方法会更好。
如果您喜欢这个答案,请投票支持,我会接受 - 如果没有人提供更好的答案。