为啥使用预处理器#if 语句而不是 if() else?

Posted

技术标签:

【中文标题】为啥使用预处理器#if 语句而不是 if() else?【英文标题】:Why use preprocessor #if statements instead of if() else?为什么使用预处理器#if 语句而不是 if() else? 【发布时间】:2014-04-06 18:13:48 【问题描述】:

我看到这一直在做,例如在 Linux 内核中。如果 else 阻塞,使用预处理器命令与普通 C++ 相比的目的是什么?有速度优势还是什么?

【问题讨论】:

你知道预处理器是做什么的吗? If it's a bad question than it will probably get removed by the mods. 不,不会。问题不会被删除,除非它们违反规则(即它们是垃圾邮件或仇恨言论或类似内容),或者已关闭并且很长一段时间没有得到赞成的答案。此问题不会不应删除。 @Konrad,这就是重点。他在问一个问题来了解预处理器的作用。没必要嘲笑他。这是一个问答网站。你知道答案,所以只要回答问题,不要抱怨。我假设您不是出生就知道预处理器的作用。 kjh 也没有 @Scott 没有嘲笑。答复将告知此处适合的答复类型。也就是说,有一种共识是,由基本教科书回答的问题不太适合 Stack Overflow,因为回答这些问题最好以教科书的方式完成,而不是用粗略的短文本来完成在许多重要细节上。 @Konrad,这很公平。这可能会带来一个更广泛的问题,即 SO 已成为许多此类问题的热门搜索结果。不管你喜不喜欢,SO 正在成为“教科书”。说“Google it”还不够好,因为 SO 是 Google 结果(无限循环)。我已经知道预处理器,所以这对我没有用,但我可以看到其他人是如何偶然发现它的。 【参考方案1】:

预处理器在编译之前更改 C/C++ 代码(因此 pre 处理器)。

预处理器 if 在编译时进行评估。

C/C++ ifs 在运行时进行评估。


您可以做一些在运行时无法完成的事情。

针对不同平台或不同编译器调整代码:

#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
#include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
#include <windows.h>
#endif

确保头文件定义只包含一次(相当于#pragma once,但更便携):

#ifndef EXAMPLE_H
#define EXAMPLE_H

class Example  ... ;

#endif

您可以使事情比运行时更快。

void some_debug_function() 
#ifdef DEBUG
    printf("Debug!\n");
#endif

现在,当使用未定义的DEBUG(可能是编译器的命令行参数)进行编译时,编译器可以优化对some_debug_function 的任何调用。

【讨论】:

尽管几乎所有编译器都支持条件包含语法,但大多数可用编译器也支持更简洁的方法是使用“#pragma once”而不是混乱的全局预处理器名称空间。跨度> if(DEBUG) printf("foo\n"); 也将使用#define DEBUG 0 优化为无(假设printf 可见),因此您可能需要调整该部分。 @Yakk:大多数编译器都会优化if (constantFalseCondition) doSomething(),甚至可以调用编译器可见的函数,该函数可以确定永远不会做任何事情。另一方面,如果条件“调试”语句需要使用不用于其他任何事情的全局缓冲区,#ifdef 可以避免在不需要时分配缓冲区;条件执行语句不能。 @Supercat 同意:这就是为什么这一点是有效的,但例子很差。 @Yakk:我读过很多人评论说语言不应该有#if 这样的东西,因为编译器可以检测和消除死代码。这种想法的一个主要问题是,大多数链接器无法消除死的全局变量,而且我认为任何链接器都不能消除 99.9% 的死变量(只有在预期需要它们的情况下将值放在那里的代码才会使用这些变量)。 【参考方案2】:

预处理器在编译通过之前运行,因此编译器甚至不会看到未采用 #if 分支中的任何内容。

#if DEBUG
int a;
#else
double b;
#endif

gcc -c -DDEBUG=1 file.c 会看到“int a”

gcc -c file.c 会看到 "double b"

【讨论】:

【参考方案3】:

预处理器允许您实际剪切或粘贴到您的源文件中,要编译的代码。如果它被剪掉,它就消失了,它就像一个注释,什么都不做,不编译,在二进制文件中不产生任何代码。开发人员通常会使用这种技术在调试版本中添加代码,以进行调试或添加或排除特定操作系统的代码。

【讨论】:

以上是关于为啥使用预处理器#if 语句而不是 if() else?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我应该使用 continue 而不是空的 if 语句? [关闭]

java,时间单独的if语句和循环而不是带有探查器的方法

前端—— JavaScript基础操作:if语句for循环while循环for...infor...of异常处理函数事件JS选择器JS操作页面样式

if 语句使用 jquery 选择器和复选框

在批处理文件中,如果满足一个条件而不是周围的 for 循环,如何突破嵌套的 if 语句?

为啥将 [super init] 放在 if 语句中,因为无论返回是不是为 nil,我们还是返回它?