预处理器如何处理“#include”指令?

How Does the Preprocessor Process "#include" Directives?

当遇到源代码中的 #include 指令时,预处理器究竟做了什么?

我假设它将 #include 替换为包含文件的内容,但我想要比我的假设更强大的东西。

有什么理由不直接将包含文件的内容键入源代码而不是 #include 除了看起来更好之外?

预处理器将用文件内容替换 #include 语句。

使用#include而不是简单地粘贴文件内容的好处是,如果头文件被修改,您只需重新编译源文件即可。如果您粘贴了文件的内容,那么您将不得不用新版本的头文件替换它。

此外,如果您 #include 一个文件位于多个位置(如常量和类型定义文件),您不必修改所有重复的声明,多次包含的文件只更改一个位置而不是几个。

来自我的 C11 标准草案第 6.10.2 节第 3 段的副本

A preprocessing directive of the form

# include "q-char-sequence" new-line

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters.

这就是 #include 个文件的意义所在。

#include <stdio.h>为例,这是一个分布式库头文件。如果您有一套项目源文件,您可能必须将 stdio.h 的内容粘贴到每个文件中。 #include 文件的全部意义在于您不必这样做。

现在取#include "mycommon.h"你本地常用的工程函数。如果您每次修改本地 mycommon.h 时都不使用 #include,则必须将其重新粘贴到所有源文件中。

Is there any reason not to type the contents of the included file straight into the source code rather than #include it other than it being nicer on the eye?

不是好看的问题

头文件的主要目的是为单独定义的函数原型和数据对象提供通用声明翻译单位。大多数重要的应用程序都包含多个模块,这些模块位于单独的翻译单元中,分别编译和 linked。一个函数或数据对象只能在一个翻译单元中定义,但可以在多个翻译单元中被引用——所有这些都必须具有正确匹配的声明 为了 link 成功。确保每个翻译单元中的 声明 正确的最简单且最不容易出错的方法是使用头文件;在多个翻译单元中输入相同的信息将很难维护。

如果另一方面,您的翻译单元包含只能在该翻译单元内访问的函数和数据(或者您的应用程序是单个翻译单元),那么相应的声明可能确实出现在同一个源文件中,并且还应声明 static 以明确禁止外部 linkage.

例如考虑标准库头文件,例如 stdio.h。例如,您可以直接在代码中输入 printf() 的原型 - 它可能看起来像:

extern int printf ( const char * format, ... );

但是您必须每次都完全正确,并且对您希望使用的每个功能都这样做。你真的会那样做吗!?