分为四个过程
预处理
编译
汇编
链接
什么是.i文件(预处理后文件)
预处理器执行宏替换、条件编译以及包含指定的文件。
什么是.s文件(汇编文件)
大概就是.i文件通过机器翻译得到的文件
什么是.o文件(可重定位目标文件(机器码文件))
由汇编文件经过汇编操作生成,该文件不可直接执行
什么是.out文件(二进制可执行目标文件(也是一个目标文件))
由机器码文件进一步链接生成。这一步中,各种符号引用和符号定义转换成为可执行文件中的合适信息,通常是虚拟地址。
预处理
源文件和头文件被预处理成一个 .i文件
预处理过程主要处理那些源文件中的以“#”开始的预编译指令。包括#include,#define, #if(#if,#ifdef,#else,#endif),等等。
#define
例如#define a b 就是先把#define删掉 然后将文件中所有单独的a都改成b
#include预编译指令
将被包含的文件插入到该预编译指令的位置
/* //
过滤所有的注释“//“和”/* */“之间的内容
还有两个不懂的
添加行号和文件名标识。比如 #2 “test.c” 2
保留所有的#pragma编译器指令,因为编译器需要使用他们
编译 汇编(.i -> .s)
编译
将经过预处理后的预编译文件转换成特定汇编代码,生成汇编文件
将.i文件进行词法分析,语法分析,语义分析以及优化后产生相应的汇编代
码文件
编译:词法分析(扫描) 语法分析 语义分析 源代码优化
词法分析
任务是将字符一个个读入源程序 应该就是分析一个个int 或者函数什么的有没有写错 就是对一个个词进行分析
简单来说就是 你写的代码在最开始机器看来就是一大堆有格式的英文字母 然后通过词法分析知道哪些是标识符 哪些是变量等等
单词类型 种别 种别码
关键字: program.if、 else、then
标识符: 变量名、数组名、记录名、过程名
常量:整型、浮点型、字符型、布尔型、
运算符: 算术(± * │++ – )关系(> <== != >= <= )逻辑(&|~)
界限符: ; (){}
例如array[index]=(index+5)*(2+7)
语法分析
将由扫描器产生的记号进行语法分析,从而产生语法树。
语法树:以表达式为结点的树。(c语言中,一个语句就是一个表达式)
词法先分析每个单词是否是对的 语法就是分析语句是否是对的
应该是int a[b];这样是错的
语法分析时很多运算符的优先级和含义也被确定下来
语义分析
应该是分析段落 例如for循环是否是正确的
例如 int a[10] ; a*10;这就是错的
编译器能分析的语义是静态语义
静态语义:在编译期间可以确实能的语义 静态语义通常包括声明和类型的匹配以及类型的转换。
动态语义:在运行期间才能确定的语义,比如将0作为除数是一个运行期语义错误。
汇编
将编译阶段生成的汇编文件转化成机器码,生成可重定位目标文件
代码生成
使用代码生成器 将中间代码转换成目标机器代码,这个代码十分依赖于目标机器,因为不同的机器(比如32位或者64位)有着不同的字长,寄存器,整数数据类型和浮点数数据类型等
目标代码优化
链接
将多个目标文件及所需要的库连接成最终的可执行目标文件
具体去看计算机操作系统