#include和实际编译的内容

时间:2013-07-23 20:28:03

标签: c compiler-construction

这只是针对基于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,是否会构建与这些标头关联的所有代码?编译器只是“粘贴”标题的内容是否正确?那么这本质上会构建一个只占用空间的无用束或头代码?

3 个答案:

答案 0 :(得分:4)

标题的所有文本都将包含在编辑中,但它们通常很少或没有效果,如下所述。

C没有任何“标题代码”的概念。对问题中文件的编译将被视为与所有包含文件的内容出现在单个文件中的情况相同。那么重要的是内容是否定义了任何对象或函数。

头文件中的大多数声明(通常使用头文件)只是声明,而不是定义。他们只是告诉编译器有关事情;它们实际上并不会导致创建对象或代码。在大多数情况下,编译器不会从非定义的声明生成任何数据或代码。

如果标头定义外部对象或函数,编译器必须为它们生成数据(或空间)或代码,因为这些对象或函数可以从其他源文件引用,以便稍后编译,然后与生成的对象链接从目前的汇编。 (某些链接器可以确定不使用外部对象或函数并将其丢弃。)

如果标题定义静态对象或函数(确切地说,具有内部链接或没有链接的对象),则编译器可以为这些生成数据或代码。但是,优化器应该看到没有引用这些对象和函数,因此可以抑制生成。这是一个简单的优化,因为它不需要任何复杂的代码或数据分析,只需观察没有任何东西取决于对象或函数。

因此,C标准并不保证不会为静态对象或函数生成任何数据或代码,但即使是中等质量的C实现也应该避免使用它,除非禁用优化。

答案 1 :(得分:1)

取决于实际的编译器。优化编译器不会为不需要的代码生成输出,而dumber编译器会生成。

gcc(一种非常常见的开源平台编译器)将使用-O选项优化您的代码,这不会生成不需要的表达式。

未定义目标的#ifdef语句中的代码将永远不会生成输出,因为这会违反语言规范。

答案 2 :(得分:1)

从概念上讲,至少包含/宏处理是与编译分开的一步。读取主源文件并构造包含所有包含代码的新临时文件。如果任何内容为“#ifdef ed out”,则该代码不包含在临时文件中。同时,宏名称的出现被它们“扩展”的文本替换。这是生成的文件,其中包含所有包含等,它们被送入实际的编译器。

有些编译器按字面意思执行此操作(您甚至可以“捕获”中间文件),而其他编译器则模拟它(如果您请求生成中间文件,则实际上需要一个完整的单独步骤)。但是大多数编译器都有一种或另一种方法来生成文件供您检查。

C / C ++标准规定了一些必须遵循的神秘规则,以确保任何“模拟”实现都不会以某种方式改变结果代码的行为,而不是“文字”方法。