源程序到可执行程序的编译过程

一份源代码,从开始产生到成为可执行程序的过程:预处理——编译——汇编——链接。

源程序到可执行程序的编译过程_第1张图片

1、预处理

— 将所有的#defind,ifdef/ifndef删除并且展开

— 处理所有条件预处理指令

— 处理#include,将其中包含的文件插入到程序中

— 过滤掉所有的// 和 /* */ 注释内容

— 保留所有的#progma编译指令

预处理并不占用运行时间,同时预处理指令本身并不是C语言的组成部分,因此预处理过程不归入编译器工作范围,而是交给独立的预编译器。

2、编译

        — 语法分析,

— 词法分析、

— 语义分析、

— 中间代码生成、

— 代码优化、

— 目标代码生成 

源程序到可执行程序的编译过程_第2张图片

编译过程就是将高级语言转换成对应硬件平台的汇编语言,生成.s/.asm文件,不同的处理器有不同的汇编格式,不如X86平台对应x86的汇编格式,ARM平台对应ARM汇编格式。

编译过程是一段翻译程序,将源程序翻译成另一种语言的目标程序,二者在逻辑上是相当的。

编译主要的工作就是检验变量、函数、标识符、关键字等使用是否合理;

具体工作分为六大部分:语法分析词法分析语义分析中间代码生成代码优化目标代码生成

编译的各个过程中时刻需要表格管理,用来记录源程序的各种各类信息和编译各个子阶段的进展情况。主要的工作是整理符号表,用以等级每个标识符以及它们的属性,比如一个标识符是常量还是变量,类型是什么, 占用内存多少,地址是多少。

编译的各个过程时刻需要出错管理,用以设法发现错误并将错误信息告知用户。

出错情况一般包含两方面:语法错误和语义错误

(1)语法错误

不合乎语法规则的错误,,比如是否拼写错误,括号是否不匹配

(2)语义错误

不合乎语义规则的错误:说明是否有错,作用域是否有错,类型是否有不匹配。

从源程序到目标程序中产生的中间结果从头到尾扫描一次,产生新的中间结果和目标程序。因此遍数多了,整个编译过程的逻辑结构会非常清晰,但同时会增加编译过程的时间损耗。

在保证正确和正常运行的情况下,遍数还是少的好。

3、汇编

将汇编语言转换成机器语言形式的目标文件,形成.o/.obj/.a/.ko目标文件,这个文件是ELF格式的可重定位文件。

可重定位文件:该文件中的函数和全局变量还未定位,因为定义和调用可以出现在不同的文件中,因此还需要链接步骤。

4、链接

将目标文件.o与启动代码,和相应的静态库或者动态库链接起来,形成.exe可执行文件;

链接分为静态链接和动态链接。

之所以需要链接,是因为汇编后的文件可重定位文件还不能直接运行,所以需要链接。

 

 

 

 

以下是一些衍生出来的问题:

1、源代码为啥需要编译?

因为处理器并不能识别由文本字符组成的源文件代码,即使经过预处理后产生的.i文件依旧是文本文件,不能被处理器识别,所以需要编译成能识别的机器码。

2、编译过程中的6大子阶段的具体工作是什么?

词法分析:对源程序进行扫描和分析,识别出一个个词,比如:标识符,常量,运算符等等;其运作中遵循的是语法规则(构词规则),描述这套规则的有效工具是正规氏和有限自动机。

语法分析:在词法分析的基础上,一句语法规则,将词分解成一个个语法单元(短句,子句,句子,程序段,程序),并判断释放符合语法正确性,比如有没有拼写错误,括号有没有不匹配?这是一种层次分析。

语义分析:对一个个语法单元进行静态语义检查(说明有没有错,作用域有没有错,类型有没有不匹配),分析其含义,判断是否合乎语法范畴,比如变量是否定义、类型是否正确等

中间代码生成:如果语法分析没错,那就进行初步翻译,产生中间代码。

代码优化:将代码(主要是针对中间代码)进行加工变换,使其能形成更加高效,更加节省时间和空间的代码。

                    优化的方面:公共表达式的提取、循环优化、删除无用代码。

                   依据的规则是程序的等价交换原则。

目标代码生成:将经过优化处理后的中间代码转换成特定机器上的低级语言程序代码,比如汇编指令。

3、一个好的出错管理,应该具备哪些特点?

(1)全:最大限度发现错误

(2)准:确定发现错误的性质个准确地址

(3)局部化:将错误产生的影响压至最小

(4)自动校正:能尽全力自动矫正错误,但这种能力往往很少。

4、目标文件由什么组成?

目标文件由段组成:

(1)代码段:存放程序的指令,可读不可写,可执行;

(2)数据段:存放程序中的用到的全局变量和静态数据,可读可写可执行;

5、编译器是通过判断文件后缀来决定是否编译该文件?

编译器是根据文件后缀名来辨别是否编译该文件的,.h文件一概忽略,.cpp文件都会被进行编译。

6、静态链接是指什么?

程序在进行编译过程中链接静态库(.a/.lib),静态库也会进行静态编译,期间,静态库中所有代码函数(无论是有用的没用的)都被拷进程序,因此编译完后程序体积非常大;

在运行可执行文件的时候,不再需要静态库的存在了甚至把静态库删了也不影响。

7、动态链接是指什么?

程序在编译过程中链接动态库,动态库不会把库的代码拷进程序,而是留下一个标记(位置及名字),告诉可执行程序所需要的库的路径,程序需要就会自己去找,因此程序体积比较轻巧。

在运行的时候,动态库必须时时刻刻存在,如果被删掉了,该程序就会执行失败。

8、一个好的编译原理的指标是什么?

(1)所有合法的程序都能运行;

(2)非法的错误都能被识别,并产生较少的连锁反应;

(3)程序出错不至于导致系统奔溃;

(4)模块化和结构化程度高;

(5)可维护性和可读性强;

 

 

 

 

 

你可能感兴趣的:(C/C++)