源程序(.c) │ 预处理(cpp) ↓ 预处理后源文件(.i) │ 编译器(cc1) ↓ 汇编语言文件(.s) │ 汇编器(as) ↓ 目标文件(.o) ←── 重定位信息 │ 链接器(ld) ↓ 可执行文件 │ 加载器(loader) ↓ 内存中运行的进程
# 开头的预编译指令——宏替换、头文件包含、条件编译;输出 `.i` 文件(纯 C 代码)。| 工具 | 输入 | 输出 | 核心任务 |
|---|---|---|---|
| 预处理器 | .c | .i | 宏替换、头文件展开 |
| 编译器 | .i | .s | 高级语言 → 汇编语言 |
| 汇编器 | .s | .o | 汇编语言 → 机器语言 |
| 链接器 | .o + .a | 可执行 | 符号解析 + 重定位 |
| 加载器 | 可执行 | 进程 | 装入内存 |
extern 声明只是引用,不是定义。| 考法 | 解题套路 |
|---|---|
| 程序转换顺序 | 预处理 → 编译 → 汇编 → 链接 |
| 各阶段的功能区分 | 编译器:高级→汇编;汇编器:汇编→机器码 |
| 链接器的功能 | 符号解析 + 重定位 |
| 静态链接 vs 动态链接 | 静态:代码复制进可执行;动态:运行时加载共享库 |
| 编译错误 vs 链接错误 | 编译:语法错误;链接:符号未定义/重复定义 |
extern)不分配空间,定义才分配。↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。