目录
总览:C++程序从源码到执行的完整过程
一、预处理(Preprocessing):处理 #include 和宏定义
二、编译(Compilation):把 C++ 转成汇编语言
️ 三、汇编(Assembly):将汇编代码转为机器码(二进制)
四、链接(Linking):把所有目标文件拼接成可执行程序
涉及两种链接:
⚙️ 五、举个实际例子:Linux下用g++编译
六、图解:C++ 构建流程
C++ 程序构建过程通常分为 4 个主要阶段:
源代码(.cpp)
↓ [预处理器 Preprocessor]
预处理后的代码
↓ [编译器 Compiler]
汇编代码(.s 或 .asm)
↓ [汇编器 Assembler]
目标文件(.o 或 .obj)
↓ [链接器 Linker]
可执行文件(.exe 或 ELF)
#include
和宏定义工具:预处理器
把 #include
文件展开为真实代码
把 #define
宏替换为实际值
去掉注释
示例:
#include
#define PI 3.14
int main() {
std::cout << PI << std::endl;
}
经过预处理后可能变成:
// 展开iostream
std::cout << 3.14 << std::endl;
✅ 输出文件:预处理后的 .i
文件(可选)
i
代表 intermediate
(中间文件)或 preprocessed input
(预处理输入)
工具:编译器(如 g++
, clang
, MSVC
)
将预处理后的 C++ 代码 ➜ 翻译成汇编代码
检查语法错误、类型检查
做一些优化(内联函数、常量传播等)
示例:
int add(int a, int b) { return a + b; }
编译后变成汇编语言 .s
文件(含 CPU 指令)
✅ 输出文件:汇编文件(.s
)
s 代表 source,特指汇编源代码(Assembly code)
工具:汇编器(Assembler)
将 .s
汇编代码 ➜ 转成机器可读的二进制 .o
(Linux)或 .obj
(Windows)文件
这就是所谓的目标文件(Object File)
✅ 输出文件:目标文件(.o
或 .obj
)
o 的意思:object,目标文件(Object File)
工具:链接器(Linker)
把多个 .o
文件组合在一起(可能还有库)
解析函数调用(谁调用谁?在内存中地址是多少?)
加入外部库函数(如 std::cout
的定义)
生成最终的 .exe
或 .out
文件
类型 | 描述 |
---|---|
静态链接 | .lib / .a 文件代码复制到程序中 |
动态链接 | 程序运行时加载 .dll / .so 文件 |
✅ 输出文件:最终可执行文件(.exe
, .out
, a.out
)
exe 的意思:executable,可执行文件(Executable)
g++ main.cpp -o myprog
你其实执行的是整个流程:
预处理器:展开头文件
编译器:转汇编
汇编器:生成 .o
链接器:生成可执行文件 myprog
你可以分阶段运行:
g++ -E main.cpp -o main.i # 仅预处理
g++ -S main.cpp -o main.s # 编译成汇编
g++ -c main.cpp -o main.o # 编译+汇编(不链接)
g++ main.o -o myprog # 链接
[C++ 源代码 .cpp]
↓ 预处理器(g++ -E)
[展开宏后的代码 .i]
↓ 编译器(g++ -S)
[汇编语言 .s]
↓ 汇编器(g++ -c)
[目标文件 .o / .obj]
↓ 链接器(g++)
[最终可执行程序 .exe / a.out]