一块代码要生成可执行程序需要经过编译(编译器完成)和链接(链接器完成)两个操作。
而编译又细分为预处理,编译和汇编(即编译=预处理+编译+汇编)
编译阶段每个源⽂件(.c为后缀的⽂件)单独处理⽣成对应的⽬标⽂件(.obj为后缀的⽂件)
链接阶段会把多个⽬标⽂件和库⽂件整合在一起处理⽣成对应的可执⾏程序(.exe⽂件)
如下图解:
1.编译
1.1.预处理
预处理阶段主要处理那些源⽂件中#开始的预编译指令。⽐如:#include,#define。
处理的规则如下:
• 将所有的 #define 删除,并展开所有的宏定义。
• 处理所有的条件编译指令,如: #if、#ifdef、#elif、#else、#endif 。
• 处理#include预编译指令,将包含的头⽂件的内容插⼊到该预编译指令的位置。这个过程是递归进⾏的,也就是说被包含的头⽂件也可能包含其他⽂件。
• 删除所有的注释
• 添加⾏号和⽂件名标识,⽅便后续编译器⽣成调试信息等。
• 或保留所有的#pragma的编译器指令,编译器后续会使⽤。
1.2.编译
编译过程又分为:词法分析、语法分析、语义分析及优化
1.2.1.词法分析
将源代码程序被输⼊扫描器,扫描器的任务就是简单的进⾏词法分析,一一读取代码中的字符中系列的记号(关键字、标识符、字⾯量、特殊字符等),但不会读取 空格,换行,制表符 等等
比如 printf( "%d" , 10 );
因为它会忽略空格,换行,制表符 等等所以下面式子是等价的
甚至可以写成以下形式也是可行的(同样等价)
如果你不想让别人看懂你写的代码你可以怎么写,(哈哈开玩笑),
这里这样的写是为了方便大家理解
1.2.2.语法分析
语法分析器,将对扫描产⽣的记号进⾏语法分析,从⽽产⽣语法树,这些语法树是以表达式为节点的树
比如语句array[index]=(index+4)*(2+6);生成的语法树
1.2.3.语义分析及优化
由语义分析器来完成语义分析,即对表达式的语法层⾯分析。编译器所能做的分析是语义的静态分
析。静态语义分析通常包括声明和类型的匹配,类型的转换等。这个阶段会报告错误的语法信息。
1.3.汇编
汇编器是将汇编代码转转变成机器可执⾏的指令,每⼀个汇编语句⼏乎都对应⼀条机器指令。就是根据汇编指令和机器指令的对照表⼀⼀的进⾏翻译,也不做指令优化。
2.链接
链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才⽣成可执⾏程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
链接解决的是⼀个项⽬中多⽂件、多模块之间互相调⽤的问题。