我知道#inclusion 通常被描述为文本复制粘贴预处理器指令。现在,如果一个标头是#include 保护的,或者是#pragma 一次的,那么我们如何描述经过第一个翻译单元到#include 所述标头的实际发生的事情?
问问题
65 次
1 回答
6
没有“第一个”翻译单元。所有翻译单元在概念上都是并行翻译的(当然,在实践中,您最终可能一次编译一个,但这没关系)。
每个翻译单元都以一张白板开始。从技术上讲,这并不完全正确,因为您可以#define
在命令行中添加 s 并且还有一些预定义的宏,但无论如何,任何翻译单元都不会拥有#define
在任何其他翻译单元中执行的 s 的“内存”。因此,尽管有警卫,标题可能会#include
多次出现。只是它不会被#include
d 多次转换为单个翻译单元。
这意味着您仍然必须注意避免多个定义:例如,如果您的标头包含一个全局变量,那么您必须确保它是const
(因此它将具有内部链接)或显式声明它inline
(将所有定义合并为一个)或extern
(抑制标题中的定义,以便您可以将定义放入单个翻译单元中)。
尽管包含保护并不能防止跨多个翻译单元的多个定义,但它们确实可以防止单个翻译单元内的多个定义,这很重要,因为即使某些实体可能在程序中定义多次,它仍然是不允许的多个定义出现在同一个翻译单元中。例如,如果您inline
在标头中有一个全局变量,那么多个翻译单元可以包含该标头,并且定义将在链接时全部折叠成一个定义,但是如果任何一个翻译单元定义了该标头,您将收到编译错误多次变化。因此,这样的标头必须具有包含保护。
于 2021-12-13T14:14:28.617 回答