Eng*_*999 26 c c++ header-files c-preprocessor
我知道这是一个常见问题,但我仍然无法完全理解它.
在从多个不同的源文件和头文件生成的C或C++程序中,当使用标题保护时,每个头文件是否只包含在整个代码中一次?
之前有人告诉我,头文件(带有包含警卫)只能在一个翻译单元中包含一次,但在整个代码中会多次包含.这是真的?
如果它在整个代码中只被包含一次,当一个文件希望包含它并且预处理器检测到它已经被包含时,那个希望使用它的文件如何知道它之前包含的代码中的位置?
Pau*_*per 30
这是一个过程:
source header source header header
\ / \ | / /
\ / \ | / /
PREPROCESSOR PREPROCESSOR
| |
V V
preprocessed code preprocessed code
| |
COMPILER COMPILER
| |
V V
object code object code
\ /
\ /
\ /
LINKER
|
V
executable
Run Code Online (Sandbox Code Playgroud)
预处理
#include这是第一步.它指示预处理器处理指定的文件,并将结果插入到输出中.
如果A包含B和C,并且B包括C,则预处理器的输出A将包括C两次处理的文本.
这是一个问题,因为它会导致重复的声明.一种补救措施是使用预处理程序变量跟踪源代码是否已被包含(也称为标题保护).
#ifndef EXAMPLE_H
#define EXAMPLE_H
// header contents
#endif
Run Code Online (Sandbox Code Playgroud)
第一次EXAMPLE_H是未定义的,预处理器将评估ifndef/ endifblock中的内容.第二次,它将跳过该块.因此处理后的输出会发生变化,定义只包含一次.
这是如此常见,以至于某些编译器实现的非标准指令更短,并且不需要选择唯一的预处理器变量:
#pragma once
// header contents
Run Code Online (Sandbox Code Playgroud)
您可以弄清楚您希望C/C++代码的可移植性以及使用哪个标头防护.
标题保护将确保每个头文件的内容在翻译单元的预处理代码中最多出现一次.
编译
编译器从预处理的C/C++生成机器代码.
通常,头文件仅包含声明,而不包括实际定义(也称为实现).编译器包含一个符号表,用于当前缺少定义的任何内容.
链接
链接器组合了目标文件.它将定义(也称为实现)与对符号表的引用相匹配.
可能是两个目标文件提供了定义,链接器将提供一个.如果您已将可执行代码放入标题中,则会发生这种情况.这通常不会在C中发生,但由于模板,它在C++中经常发生.
标题"代码",无论是声明还是定义,都包含在所有目标文件中多次,但链接器将所有这些文件合并在一起,因此它只在可执行文件中出现一次.(我排除了多次出现的内联函数.)
too*_*ite 16
在编译开始之前,预处理器实际插入了"头文件".只需将其视为"替换"其#include指令即可.
守卫 ...
#ifndef MY_HEADER_H
#define MY_HEADER_H
....
#endif
Run Code Online (Sandbox Code Playgroud)
...在更换后执行.因此,标题实际上可能被多次包含,但文本的"保护"部分仅由预处理器传递给编译器一次.
因此,如果标题中有任何代码生成定义,它们 - 当然 - 将包含在编译单元的对象文件中(也称为"模块").如果#include在多个模块中使用相同的标头,则这些标头将多次出现.
对于static定义,这根本不是问题,因为这些在模块之外是不可见的(也就是文件范围).对于程序全局定义,这是不同的,将导致"多个定义"错误.
注意:这主要是针对C的.对于C++,存在显着差异,因为类等会为允许多个全局对象的时间/时间增加额外的复杂性.
每个翻译单元只包含一个带有相应包含警卫的头文件.严格地说,可以包含多次,但预处理器之间的部分,并会在随后的夹杂物跳过.如果正确完成,这应该是文件的全部(或大部分).#ifndef#endif
翻译单元通常对应于"源文件",尽管一些模糊的实现可能使用不同的定义.如果单独编译的源文件包含相同的头,则预处理器无法知道另一个文件已包含它,或者任何其他文件是同一项目的一部分.
请注意,当您将多个源文件(转换单元)链接到一个二进制文件中时,如果标头不仅包含声明,模板,标记的函数定义或静态变量定义,则可能会遇到多个定义的问题inline.为避免这种情况,您应该在标题中声明函数并在单独的源文件中定义它们,您将其与其他源文件链接在一起.