0

在学校里,我经常被告知预处理器语句很容易出错,因为您定义的字符串,例如:

#define PI 3.1415926

在代码中的每个位置都被替换,当变量名包含字符串时会导致奇怪的替换PI

因此,在调试时,我会避开以下方法:

#define _DEBUG
...
#ifdef _DEBUG
    // debug code
#endif
...

但坚持使用它会“更安全”:

const static bool DEBUG = true
int main()
{
    ...
    if(DEBUG){ /* debug code*/ }
    ...
}

这很好用,但我想知道,与预处理器语句方法相比,这种方法的运行时开销是什么?使用预处理器方法,一切都发生编译之前,因此不会出现运行时开销。

我知道一个简单的if-statement 的开销几乎可以忽略不计,但是当它深入到一些运行大量时间的嵌套循环中时,这并不成立(小事加起来就是大事)。

DEBUG编译器是否识别出事实const static并将其硬编码到可执行文件中,已经在编译时启用或禁用调试代码?让我怀疑的是,前几天,在处理一些不相关的代码时,编译器警告我代码的某些部分已经过时,因为if围绕它的 -statement 永远不会成为真的(如果我没记错的话)。

4

4 回答 4

3

不可能给出硬性保证:这取决于每个单独的编译器如何处理您提供给它的代码。

但是,任何现实世界的编译器都会为您优化这一点。它是现有的最简单、最微不足道的优化之一,即使您禁用优化,大多数编译器也可能会这样做。

为本质上的内容生成代码是没有意义的if (true)

所以在运行时应该有零开销。

于 2012-04-09T13:05:38.803 回答
3

如果编译器可以静态(在编译时)确定它永远不会运行,则标准中没有任何内容说编译器不能完全省略一段代码。

另一方面,标准中也没有任何内容说编译器必须进行优化(在一般情况下)。

所以如果你给你的编译器足够的信息,并打开它的优化特性,它很可能会完全消除这些分支。但唯一可以确定的方法是查看生成的代码。

对于像这样的“微不足道的”调试启用代码,大多数现代编译器将在大多数情况下完全消除死块。

于 2012-04-09T13:06:29.503 回答
1

在学校里,我经常被告知预处理器语句很容易出错,因为您定义的字符串,例如:

#define PI 3.1415926

在代码中的每个位置都被替换,当变量名包含字符串 PI 时会导致奇怪的替换

不,PI只替换整个单词 (token) PI,而不是在另一个标记内。例如myPI不展开PI

于 2012-04-09T14:41:02.503 回答
0

这是一个细节,但由于 DEBUG 现在是一个 const bool,你应该用小写字母写它:

const static bool debug = true;

大写名称保留给预处理器宏。

于 2014-09-09T16:54:33.787 回答