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;
    

相关推荐

  1. C语言深入学习 --- 7.程序编译

    2024-04-13 22:48:03       18 阅读
  2. C语言程序编译和链接

    2024-04-13 22:48:03       24 阅读
  3. vscode编译和调试wsl环境c语言程序

    2024-04-13 22:48:03       10 阅读
  4. Android 编译C程序APP

    2024-04-13 22:48:03       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-13 22:48:03       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-13 22:48:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-13 22:48:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-13 22:48:03       20 阅读

热门阅读

  1. 【LeetCode热题100】45. 跳跃游戏 II(贪心)

    2024-04-13 22:48:03       17 阅读
  2. C# WPF故障记录

    2024-04-13 22:48:03       15 阅读
  3. 【00150】金融理论与实务-2023年4月自考真题

    2024-04-13 22:48:03       15 阅读
  4. 设计模式-里氏替换原则

    2024-04-13 22:48:03       17 阅读
  5. PyTorch 中的【高级索引】 或 【花式索引】

    2024-04-13 22:48:03       16 阅读
  6. 【图论】链式前向星实现图的BFS搜索

    2024-04-13 22:48:03       13 阅读
  7. Soulver v3.10.3.1 mac版 智能文本计算器 兼容 M1/M2/M3

    2024-04-13 22:48:03       21 阅读
  8. Ant Design Vue Table 自定义渲染与自定义单元格

    2024-04-13 22:48:03       13 阅读
  9. 【LeetCode刷题记录】76. 最小覆盖子串

    2024-04-13 22:48:03       10 阅读
  10. dfs板子

    dfs板子

    2024-04-13 22:48:03      11 阅读
  11. 蓝桥杯 2021 省 AB 2 洛谷P8755 负载均衡

    2024-04-13 22:48:03       17 阅读