T.C。我对这个问题的回答留下了一个有趣的评论:
Why aren't include guards in c++ the default?
T.C。规定:
有“标题”,还有“源文件”。 “标题”不需要 实际文件。
这是什么意思?
仔细阅读标准,我看到对“头文件”和“标题”的大量引用。但是,关于#include
,我注意到该标准似乎引用了“标题”和“源文件”。 (C ++ 11,§16.2)
A preprocessing directive of the form
# include < h-char-sequence> new-line
searches a sequence of implementation-defined places for a header identified uniquely
by the specified sequence between the < and > delimiters, and causes the replacement
of that directive by the entire contents of the header. How the places are specified
or the header identified is implementation-defined.
和
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. The named source *file*
is searched for in an implementation-defined manner.
我不知道这是否重要。可能是C ++上下文中的“标题”明确地表示“头文件”,但单词“sources”将是不明确的,因此“标题”是简写,但“来源”不是。或者可能是C ++编译器允许支架包含的余地,只需要像发生文本替换一样。
那么标题(文件)何时不是文件?
T.C.提到的脚注在下面的评论中非常直接:
174)标题不一定是源文件,也不是序列 由&lt;界定和&gt;在标题名称中必然是有效的源文件 名字(16.2)。
答案 0 :(得分:15)
对于标准标题&#34;文件&#34; C ++标准并没有真正强制要求编译器使用文件,或者文件(如果使用文件)实际上看起来像C ++文件。相反,指定标准头文件以使C ++程序可以使用某组声明和定义。
文件的替代实现可以是在编译器中表示为数据结构的容易打包的声明集,当使用相应的#include
- 指令时可以使用该声明。我不知道有任何编译器确实如此,但clang开始实现module system,这使得标头可以从一些已处理的格式中获得。
答案 1 :(得分:7)
它们不一定是文件,因为C和C ++预处理器是nearly identical,因此可以合理地查看C99的基本原理。如果我们查看7.1.2
部分Rationale for International Standard—Programming Languages—C中所说的标准标题表示(强调我的):
在许多实现中,标头的名称是文件的名称 特殊目录。这种实现技术不是必需的, 但是:标准没有假设文件的形式 名称可以采用任何系统。因此,标题可能具有特殊状态 一个如此选择的实现。标准标题甚至可以内置 翻译,只要他们的内容不会被“知道”,直到 在明确包含它们之后。允许这些的一个目的 要翻译成“内置”的标题“文件”是允许的 实施C语言作为独立翻译 唯一“文件”支持可能是网络接口的环境。
答案 2 :(得分:3)
这实际上取决于文件的定义。
如果您考虑将文件名映射到内容的任何数据库都是文件系统,那么是,标题是文件。如果您只考虑文件是操作系统内核open
系统调用识别的文件,那么不,标题不一定是文件。
它们可以存储在关系数据库中。或压缩档案。或者通过网络下载。或者存储在编译器可执行文件本身的备用流或嵌入资源中。
最后,文本替换已完成,文本来自某种索引名称数据库。
Dietmar提到模块并加载已处理的内容......但根据C ++标准,这通常是#include
不允许的行为(模块必须使用不同的语法,或者#include
除<>
或""
之外的全新引用方案。可以提前完成的唯一处理是标记化。但是标题和包含的源文件的内容都要进行有状态的预处理。
有些编译器实现了“预编译头”,这些头已经完成了比标记化更多的处理,但最终你发现了一些违反标准的行为。例如,在Visual C++中:
编译器...跳过超出与.h文件关联的
#include
指令,使用.pch文件中包含的代码,然后在 filename 之后编译所有代码
忽略#include
之前的实际源代码肯定不符合标准。 (这并不妨碍它有用,但你需要知道编辑可能不会产生预期的行为变化)