老是记不住,老是混淆
前言
从代码编写到可执行文件的执行
一、预处理阶段(Preprocessing)
代码完成之后,广义编译(程序构建过程)的第一个阶段就是预处理阶段
在预处理阶段,预处理器负责处理源文件中的预处理指令,主要包括:
- 宏替换:将代码中的宏(#define)替换为对应的内容。
- 文件引入:将通过 #include 指令引入的头文件内容插入到源文件中。
- 条件编译:根据条件预处理指令(如 #ifdef、#ifndef)决定是否编译某些代码片段。
预处理的作用:
确保头文件被正确包含到源代码中。
处理宏定义,替换代码中的宏。
处理条件编译。
预处理输出的是扩展后的源代码文件。
预处理后将从文件 main.cpp 生成文件 main.i
二、编译阶段(Compilation)
预处理阶段之后,就来到了编译阶段
在编译阶段,编译器会将预处理过的源代码转换为中间代码,再从中间代码转为汇编代码,并检查代码的语法和语义。这一步骤主要处理以下内容:
- 语法检查:确保代码符合 C++ 语言的语法规范。
- 类型检查:检查变量和函数的类型是否一致,是否进行了正确的类型转换。
- 生成汇编代码:编译器将源代码翻译成目标平台对应的汇编代码。
- 编译器的输出是汇编代码文件(如 .s 文件)。
编译后将生成汇编代码文件 main.s
三、汇编阶段(Assembly)
在编译阶段之后,就来到了汇编阶段
在汇编阶段,汇编器将汇编代码(.s 文件)转换为机器码,即对应的二进制指令。这些二进制指令是 CPU 可以理解和执行的低级指令。汇编阶段生成的是目标文件(.o 文件)。
目标文件是一个二进制文件,但它并不包含完整的程序。它只包含当前源代码中定义的函数和变量的机器码,没有外部函数或库的定义(例如 std::cout 还没有被链接进来)。
汇编后将生成目标文件 main.o
四、链接阶段(Linking)
在汇编阶段之后,就来到了链接阶段
链接阶段的任务是将所有的目标文件(.o 文件)以及需要的库文件(如 C++ 标准库 libstdc++)链接在一起,生成最终的可执行文件。
内部链接:将各个目标文件(例如多个 .cpp 文件生成的 .o 文件)中的符号(如函数或变量)进行关联。
外部链接:将程序所依赖的外部库文件(如 std::cout 所在的标准库)与目标文件链接在一起。
如果缺少某些库或未定义的符号,链接阶段就会报错。链接的结果是生成一个完整的可执行文件。
链接后将生成可执行文件 main
五、运行阶段(Execution)
生成的可执行文件可以直接在系统中运行。在这个阶段,操作系统会加载可执行文件到内存中,初始化全局变量,执行 main 函数,并最终完成整个程序的运行。
总结
广义编译指的就是程序的整个构建过程
狭义编译指的是整个构建过程中的编译阶段