C程序的编译

经过预处理后的源文件,退去一切包装,注释被删除,各种预处理命令也基本上被处理掉,剩下的就是原汁原味的C代码了。接下来的第二步,就开始进入编译阶段。编译阶段主要分两步:第一步,编译器调用一系列解析工具,去分析这些C代码,将C源文件编译为汇编文件;第二步,通过汇编器将汇编文件汇编成可重定位的目标文件。

从C文件到汇编文件

从C文件到汇编文件,其实就是从高级语言到低级语言的转换。通过前面的学习我们知道,一个汇编文件是以段为单位来组织程序的:代码段、数据段、BSS段等,各个段之间相互独立。我们可以使用AREA或.section伪操作来定义一个段。

看到这里,聪明又机智的你可能已经发现:汇编程序的组织结构和二进制目标文件已经很接近了。没错,两者本质上其实就是等价的,汇编指令就是二进制指令的助记符,唯一的差异就是汇编语言的程序结构需要使用各种伪操作来组织。汇编文件经过汇编器汇编后,处理掉各种伪操作命令,就是二进制目标文件了。

从C源文件到汇编文件的转换,其实就是将C文件中的程序代码块、函数转换为汇编程序中的代码段,将C程序中的全局变量、静态变量、常量转换为汇编程序中的数据段、只读数据段。道理很简单,但真正实现起来却没那么简单,别的不说,就单单C语句解析就是一门大学问。总体来讲,编译过程可以分为以下6步。

  1. 词法分析;
  2. 语法分析;
  3. 语义分析;
  4. 中间代码生成;
  5. 汇编代码生成;
  6. 目标代码生成;

词法分析是编译过程的第一步,主要用来解析C程序语句。词法分析一般会通过词法扫描器从左到右,一个字符一个字符地读入源程序,通过有限状态机解析并识别这些字符流,将源程序分解为一系列不能再分解的记号单元——token。token是字符流解析过程中有意义的最小记号单元,常见的token如下。

  • C语言的各种关键字:int、float、for、while、break等。
  • 用户定义的各种标识符:函数名、变量名、标号等。
  • 字面量:数字、字符串等.
  • 运算符:C语言标准定义的40多个运算符。
  • 分隔符:程序结束符分号、for循环中的逗号等。

假如我们的C源程序中有下面这么一条语句。

sum = a + b / c

经过词法扫描器扫描分析后,就分解成了8个token:“sum”“=”“a”“+”“b”“/”“c”“;”,很多C语言初学者在编写程序时,不小心输入了中文符号、圆角/半角字符导致编译出错,其实就发生在这个阶段。

词法分析结束后,接着进行语法分析。语法分析主要是对前一阶段产生的token序列进行解析,看是否能构建成一个语法上正确的语法短语(程序、语句、表达式等)。语法短语用语法树表示,是一种树型结构,不再是线性序列。如图所示,上面的token序列,经过语法分析,就可以分解为一个语法上正确的语法树。

在这里插入图片描述

语法分析工具在对token序列分析过程中,如果发现不能构建语法上正确的语句或表达式,就会报语法错误:syntax error。如果程序语句后面少了一个语句结束符分号或者在for循环中少了一个分号,报的错误都属于这种语法错误。大家在调试程序时,再遇到syntaxerror的字眼,应该知道问题出在什么地方了吧。

语法分析如果没有出现什么错误,接下来就会进入下一阶段:语义分析。语法分析仅仅对程序做语法检查,对程序、语句的真正意义并不了解,而语义分析主要对语法分析输出的各种表达式、语句进行检查,看看有没有错误。如果你传递给函数的实参与函数声明的形参类型不匹配,或者你使用了一个未声明的变量,或者除数为零了,break在循环语句或switch语句之外出现了,或者在循环语句之外发现了continue语句,一般都会报语义上的错误或警告。

语义分析通过后,接下来就会进入编译的第四个阶段:生成中间代码。在语法分析阶段输出的表达式或程序语句,还是以语法树的形式存储,我们需要将其转换为中间代码。中间代码是编译过程中的一种临时代码,常见的有三地址码、P-代码等。

中间代码和语法树相比,有很多优点:中间代码是一维线性序列结构,类似伪代码,编译器很容易将中间代码翻译成目标代码。如上面的表达式语句。

int main(void)
{
   
    int  sum=0;
    
  • 30
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值