一、翻译环境 & 运行环境
在标准 C(ANSI C)中,程序处理分为两个独立环境:
- 翻译环境 :将
.c源代码,转换为二进制的可执行机器指令(编译 + 链接阶段)。 - 运行环境 :执行可执行程序,输出运行结果。
整体流程:多个.c源文件 → 翻译环境 →可执行程序 → 运行环境 → 输出结果
二、翻译环境的完整流程
翻译环境 = 编译 + 链接 其中编译 又细分为:预处理(预编译)→ 编译 → 汇编
1. 编译阶段
- 多个
.c文件单独编译 ,每个文件生成目标文件- Windows 系统:后缀为**
.obj** - Linux 系统:后缀为**
.o**
- Windows 系统:后缀为**
- 工具:编译器(Windows 常用
cl.exe,Linux 常用gcc)
2. 链接阶段
- 参与文件:所有编译生成的目标文件 + 链接库(系统运行时库、第三方库)
- 工具:链接器(Windows 常用
link.exe) - 最终产物:可执行程序 (Windows 为
.exe,Linux 为无后缀可执行文件)
2.1 预处理(预编译)
核心作用
处理源文件 / 头文件的预编译指令 ,生成后缀为 .i 的纯 C 代码文件。
GCC 实操命令
gcc -E test.c -o test.i
主要处理规则
- 宏处理 :删除
#define,完全展开所有宏定义; - 条件编译 :处理
#if/#ifdef/#elif/#else/#endif; - 头文件嵌入 :递归展开
#include,把头文件内容直接插入源码; - 清理注释:删除所有单行 / 多行注释;
- 调试标记:添加行号、文件名标识,用于后续调试;
- 保留指令 :保留
#pragma编译器指令。
💡 排查技巧:宏定义、头文件包含异常时,可直接查看.i文件定位问题。
2.2 编译
核心作用
对预处理后的.i文件 ,依次做词法分析→语法分析→语义分析→代码优化 ,生成汇编代码文件(.s)。
GCC 实操命令
gcc -S test.i -o test.s
2.2.1 词法分析
- 原理:扫描器 将代码字符切割为记号(关键字、标识符、字面量、运算符等);
- 示例:代码
array[index] = (index+4)*(2+6);经过词法分析后,会被拆分为16 个独立记号,完成字符到代码单元的转换。

后续编译流程
词法分析后还会执行:
- 语法分析 :构建语法树,检查语法格式是否合法;
- 语义分析:检查类型匹配、作用域、表达式合法性;
- 代码优化 :简化冗余计算(示例中
2+6会直接优化为8)。
2.3 汇编
核心作用
将编译生成的汇编代码(.s) ,翻译为二进制机器指令 ,生成目标文件。
- 特点:逐条翻译、几乎不做优化,一条汇编语句对应一条机器指令。
- 文件后缀:Linux 为
.o,Windows 为.obj
GCC 实操命令
gcc -c test.s -o test.o
2.4 链接
核心作用
将多个目标文件 + 系统库文件 整合,解决多文件 / 多模块调用问题 ,最终生成可执行程序。
三大核心步骤
- 地址和空间分配:统一规划所有代码、数据的内存布局
- 符号决议 :匹配函数、全局变量的声明与定义
- 重定位:修正跨模块调用的地址,补全真实内存地址
实例解析(test.c + add.c)
test.c用extern声明外部函数Add、全局变量g_val,但编译时不知道真实地址;add.c定义Add函数和g_val全局变量;- 两个文件分别编译生成
test.o、add.o; - 链接器找到
Add、g_val真实地址,修正test.o中的调用指令,该过程即重定位。
底层拓展
- 目标文件格式:Linux 下为 ELF 格式
- 推荐书籍:《程序员的自我修养》(详解链接底层原理)
三、运行环境
1. 程序载入内存
- 操作系统环境(Windows/Linux):由操作系统自动完成,操作系统从磁盘读取可执行文件,分配内存空间,将程序加载到内存。
- 裸机 / 独立环境(单片机、嵌入式) :无操作系统,需手动载入,或直接将编译后的可执行代码烧录到只读存储器(ROM/Flash)中。
2. 启动执行,调用main函数
程序加载完成后,系统 / 硬件初始化完成,自动调用main()函数 ,main是 C 程序的唯一入口。
3. 代码执行,内存使用
程序运行时主要用到两类内存:
- 运行时栈(Stack)
- 用于存储局部变量、函数调用返回地址
- 函数调用时自动分配,函数结束后自动释放,生命周期随函数。
- 静态内存(static)
- 存储
static修饰的静态变量、全局变量 - 程序整个运行期间都保留值,不会随函数结束释放。
- 存储
补充:还有堆(Heap) ,用于
malloc/free动态内存分配。
4. 程序终止
- 正常终止 :
main函数执行完毕返回(return 0)。 - 意外终止:程序崩溃、强制关闭、异常报错等。