这只是一个一般编译器问题,针对基于 C 的语言。
如果我有一些如下所示的代码:
#include "header1.h"
#include "header2.h"
#include "header3.h"
#include "header4.h" //Header where #define BUILD_MODULE is located
#ifdef BUILD_MODULE
//module code to build
#endif //BUILD_MODULE
即使未定义 BUILD_MODULE,与这些标头关联的所有代码都会构建吗?编译器只是“粘贴”标题的内容,正确吗?那么这实际上会构建一堆无用的代码或头代码,只会占用空间?
标题的所有文本都将包含在编译中,但它们通常影响很小或没有影响,如下所述。
C 没有任何“头代码”的概念。问题中文件的编译将被视为与所有包含文件的内容出现在单个文件中相同。那么重要的是内容是否定义了任何对象或函数。
头文件中的大多数声明(因为头文件很常用)只是声明,而不是定义。它们只是告诉编译器一些事情;它们实际上并不导致创建对象或代码。在大多数情况下,编译器不会从不是定义的声明生成任何数据或代码。
如果头文件定义了外部对象或函数,编译器必须为它们生成数据(或空间)或代码,因为这些对象或函数可以从其他源文件中引用,以便稍后编译,然后与从头文件生成的对象链接当前编译。 (某些链接器可以确定未使用外部对象或函数并丢弃它们。)
如果标头定义了静态对象或函数(准确地说,是具有内部链接或无链接的对象),那么编译器可能会为它们生成数据或代码。然而,优化器应该看到这些对象和函数没有被引用,因此生成可能会被抑制。这是一个简单的优化,因为它不需要任何复杂的代码或数据分析,只需观察不依赖于对象或函数。
因此,C 标准不保证不会为静态对象或函数生成任何数据或代码,但即使是中等质量的 C 实现也应该避免它,除非禁用优化。
取决于实际的编译器。 优化编译器不会生成不需要的代码的输出,而较笨的编译器则会生成输出。
gcc(开源平台上非常常见的 c 编译器)将使用 -O 选项优化您的代码,这不会生成不需要的表达式。
#ifdef 语句中未定义目标的代码永远不会生成输出,因为这会违反语言规范。
至少从概念上讲,包含/宏处理是与编译分开的步骤。 读取主源文件并构造一个新的临时文件,其中包含所有包含的代码。 如果有任何内容被“删除”,则该代码不会包含在临时文件中。 同时,宏名称的出现将被它们“扩展”成的文本替换。 正是生成的文件(包含所有包含内容等)被输入到实际的编译器中。
一些编译器按字面意思执行此操作(您甚至可以“捕获”中间文件),而其他编译器则进行模拟(如果您请求生成中间文件,实际上需要一个完整的单独步骤)。 但大多数编译器都有一种或另一种方法来生成文件供您检查。
C/C++ 标准制定了一些相当晦涩的规则,必须遵循这些规则,以确保任何“模拟”实现不会以某种方式改变生成代码的行为,而不是“字面”方法。