在ANSI C的任何⼀种实现中,存在两个不同的环境。
第1种是翻译环境,在这个环境中源代码被转换为可执⾏的机器指令。
第2种是执行环境,它⽤于实际执⾏代码
翻译环境
一个程序可能不止一个.c文件
• 多个.c⽂件单独经过编译出编译处理⽣产对应的目标文件
• 多个⽬标⽂件和链接库⼀起经过链接器处理⽣成最终的可执⾏程序。
• 链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库。
1.将所有的#define删除,展开所有的宏定义
//预处理前
#define M 5
int main()
{
int a = M;
return 0;
}
//预处理后
int main()
{
int a=5;
return 0;
}
2.处理所有的条件编译指令,如:#if、#ifdef、#elif、#else、#endif 。
3.处理#include 预编译指令,将包含的头⽂件的内容插⼊到该预编译指令的位置。这个过程是递归进⾏的,也就是说被包含的头⽂件也可能包含其他⽂件。
#include
//将头文件插入到目标文件中
4.删除所有的注释,以减小目标文件的大小。
5.添加行号和文件名标识,⽅便后续编译器⽣成调试信息等。
6.或保留所有的#pragma的编译器指令,编译器后续会使⽤。
把c语言代码翻译成汇编代码
编译过程就是将预处理后的⽂件进⾏⼀系列的:词法分析、语法分析、语义分析及优化,⽣成相应的汇编代码⽂件。
对下⾯代码进⾏编译的时候,会怎么做呢?假设有下⾯的代码
array[index] = (index+4)*(2+6);
将代码分割成一系列的记号,例如**(关键字、标识符、字⾯量、特殊字符等)**
接下来语法分析器,将对扫描产⽣的记号进⾏语法分析,从⽽产⽣语法树。这些语法树是以表达式为节点的树。
由语义分析器来完成语义分析,编译器所能做的分析是语义的静态分析。通常包括声明和类型的匹配,类型的转换等。这个阶段会报告错误的语法信息。
4)符号汇总
在后面链接部分会讲到
汇总的符号一般是全局的符号
把汇编代码翻译成了二进制的指令生产了.o文件(目标文件),生成符号表
汇编器是将汇编代码转转变成机器可执⾏的指令,每⼀个汇编语句⼏乎都对应⼀条机器指令。就是根
据汇编指令和机器指令的对照表⼀⼀的进⾏翻译,也不做指令优化
链接目标文件和链接库生成可执行程序二进制程序
1.符号表的汇总
2.符号表的合并和重定义
前面我们说到在编译过程中会进行符号汇总。
在如下add.c文件中,汇总到一个 Add符号
在test.c文件中,汇总到 Add和main
码字不易,感谢观看。
如果对你有帮助的话,记得点赞+评论+关注哦