【发布时间】:2020-06-17 15:38:03
【问题描述】:
我想更深入地了解为什么要使用标头,经过一些研究,我找到了一些令人信服的答案,但在大多数回复中,人们说它可以加快编译速度,但所有这些答案都含糊不清,并没有确切说明如何头文件使编译更容易。 有人可以更深入地研究这个主题吗? 谢谢。
【问题讨论】:
标签: c header compiler-construction
我想更深入地了解为什么要使用标头,经过一些研究,我找到了一些令人信服的答案,但在大多数回复中,人们说它可以加快编译速度,但所有这些答案都含糊不清,并没有确切说明如何头文件使编译更容易。 有人可以更深入地研究这个主题吗? 谢谢。
【问题讨论】:
标签: c header compiler-construction
如果您从头开始编译,将项目分成标头不会提高编译速度。
但是,它们使修改代码的速度更快。项目的编译通常是这样的。首先,您将每个文件编译成具有相对地址的机器代码(因此代码的起始地址未知)。然后链接所有其他文件以创建您的项目。
假设您有一个包含 10.000 个文件的项目。如果仅更改 1 个文件,则在构建项目时仅编译该文件,然后将链接所有其他文件。如果您没有将项目划分为 10.000 个文件,则在构建简单更改时,您必须编译所有其他 10.000 个文件。因此,一旦您编译了项目,使用这种方法调试会变得相当快。
另外,编译文件是一个单线程程序。因此,您可以通过将多个文件一起编译来并行化编译速度。 -j 标志 make 命令执行此操作。
【讨论】:
忘记编译速度。问题是软件的可维护性。
标头旨在包含不同来源在编译时所需的内容,通常是构成 API 的 #define 常量和函数声明。
【讨论】:
一些编译器(实际上只是 MSVC)可以很好地利用预编译头文件。这实际上意味着如果您在每个编译单元的开头都有相同的包含文件,那么您可以告诉编译器只处理一次,并且对于每个其他编译单元,仅在该包含之后才开始处理。
如果您看到带有 stdafx.h 标头的项目会引入整个项目中常用的许多其他标头,那么就是这样。
gcc 或 clang 等其他编译器在处理源代码时要快得多,因此缓存这种不完整的表示还没有任何好处。
除了预编译的头文件外,它们还用作编译单元之间的公共接口。在谈论带有模板的 C++ 或带有模板生成过多代码的 C 时,有时在编译阶段将生成的符号的可见性限制在特定的编译单元中会有所不同。为了在以下链接阶段限制可见性,static 关键字是要使用的关键字。
实际上,这不会影响大多数项目。事实上,对于较小的项目,一种常见的技术实际上是在编译之前连接所有编译单元,以便在编译时消除分离,而不需要专门的链接步骤。鉴于合并的编译单元中的静态符号没有冲突,这实际上往往比在标头中严格使用最小接口节省更多的编译时间。
根据实际经验估计,一旦在单个编译单元中可见超过 50-100k 个符号,出于编译器性能原因,您需要开始降低可见性。
【讨论】: