C语言的编译过程
C语言真正的编译过程(4个步骤~~预编译,编译,汇编,连接) - wdliming - 博客园
(4 封私信 / 67 条消息) C语言的编译过程详解 - 知乎
C语言的编译过程就是把我们可以理解的高级语言代码转换为可理解的机器代码的过程,其实就是一个翻译的过程。
它包括四个步骤,预处理,编译,汇编,连接
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("hello world!\n");
return 0;
}
预处理
C语言的macro(宏)是一种预处理指令,通过#define定义,在编译前的预处理阶段进行文本替换,主要用于简化代码、增强可读性和实现灵活编程。
#define PI 3.14159 // 预处理后所有PI替换为3.14159
这样修改常量时只需要调整宏定义,无需逐个修改代码中的值。
宏可封装重复代码,减少冗余。例如:
#define SQUARE(x) ((x) * (x)) // 计算平方
使用时
SQUARE(5)
会被替换为((5) * (5))
,避免重复编写相同逻辑
预处理过程实质上是处理#,将#include包含的头文件直接拷贝到hell.c中。具体做的事情如下
- 将所有的#define扇出,并且展开所有的宏定义 ,说白了就是字符串替换
- 处理所有的条件编译指令,#ifdef #ifndef #endif等,就是带#的那些
- 处理#include,将#include指向文件插入到该行处
- 删除所有注释
- 添加行号和文件表示,这样在调试和变异出错的时候才知道哪个是文件的哪一行
- 保留#pragma编译器指令,因为变异器需要使用它们。
编译
编译的过程实质上是把高级语言翻译成机器语言的过程,因为a.c做了这些事
- 词法分析:将代码拆分为标记(tokens),如关键字、变量名等。
- 语法分析:构建抽象语法树(AST),检查语法正确性。
- 语义分析:验证变量类型、函数调用等逻辑合法性。
- 优化与汇编生成:优化中间代码并生成目标平台的汇编指令(如x86或ARM架构)
汇编代码是一种简单的语言,用于编写低级指令(在微控制器程序中,我们使用汇编语言。)整个程序代码有编译器软件一次解析(语法分析),通过终端窗口告诉我们源代码中存在的任何语法错误或警告。
汇编(assembly)
汇编器将汇编代码(.s文件)翻译成机器码,生成目标文件(.o或.obj)这一阶段的核心操作包括
生成的文件与程序集文件同名,在 DOS 中称为扩展名为 .obj 的对象文件,在 UNIX 操作系统中扩展名为 .o。
- 指令翻译:将汇编指令(如mov、call)转化成二进制机器码
- 生成目标文件:包含代码段,数据段和符号。
链接
链接器将多个目标文件(.o)和库文件(如c语言标准库)合并为可执行文件。
链接是将库文件包含在我们程序中的过程。库文件是一些预定义的文件,其中博阿含机器语言中函数定义,这些文件的扩展名为.lib。一些位置语句写入我操作系统无法理解对象(.o/.obj) 文件中。
- 符号解析:匹配函数和变量的引用与定义(如printf的实现)
- 地址重定位:为符号分配实际内存地址,修正跨文件调用指令
- 库处理:静态链接(.a或.lib)将库代码嵌入可执行文件,动态链接(.so或.dll)在运行时加载