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;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/616448.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AcWing】蓝桥杯集训每日一题Day16|哈希|FloodFill算法|字典序最小|映射|1402.星空之夜(C++)

1402.星空之夜 1402. 星空之夜 - AcWing题库难度:中等时/空限制:1s / 64MB总通过数:3415总尝试数:7434来源:usaco training 5.1算法标签Flood Fill哈希DFSBFS 题目内容 夜空深处,闪亮的星星以星群的形式出…

智慧公厕功能与应用

智慧公厕是智慧城市建设中极为重要的组成部分,它以其先进的功能和智能化的应用,为市民提供舒适、便利、安全的卫生设施。下面将以智慧公厕源头实力厂家广州中期科技有限公司,大量精品案例项目现场实景实图实例,深入探讨智慧公厕的…

FRDM-MCXN947开发板之RGB灯

一、背景 RGB LED:通过红、绿、蓝三种颜色组合发光的LED,可以理解由三个不同发光属性的LED组成,这个是LCD平板显示原理的基础,一个LED相当于屏幕上面的一个像素 FRDM-MCXN947集成了一块RGB LED,它由三个GPIO口驱动&am…

从零开始写一个RTSP服务器(一)RTSP协议讲解

目录 前言一、什么是RTSP协议?二、RTSP协议详解2.1 RTSP数据格式2.2 RTSP请求的常用方法2.3 RTSP交互过程2.4 sdp格式 三、RTP协议3.1 RTP包格式3.2 RTP OVER TCP 四、RTCP 前言 为什么要写这个系列? 因为我自己在学习rtsp协议想自己从零写一个rtsp服务…

【hive】lateral view侧视图

文档地址:https://cwiki.apache.org/confluence/display/Hive/LanguageManualLateralView 1.介绍2.语法3.code demo1)单重侧视图2)多重侧视图3)tips:lateral view outer 1.介绍 lateral view也叫侧视图,属…

【网站项目】农产品自主供销小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

【前端】layui table表格勾选事件,以及常见模块

欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是《前端》系列文章,每篇文章将以博主理解的角度展开讲解, 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 表格勾选事…

【自研网关】过滤器链设计

🌈Yu-Gateway::基于 Netty 构建的自研 API 网关,采用 Java 原生实现,整合 Nacos 作为注册配置中心。其设计目标是为微服务架构提供高性能、可扩展的统一入口和基础设施,承载请求路由、安全控制、流量治理等…

day9 | 栈与队列 part-1 (Go) | 232 用栈实现队列、225 用队列实现栈

今日任务 栈与队列的理论基础 (介绍:代码随想录)232 用栈实现队列(题目: . - 力扣(LeetCode))225 用队列实现栈 (题目: . - 力扣(LeetCode) ) 栈与队列的理论基础 栈 : 先进后出 队列: 后进先出 老师给的讲解:代码随想录 …

基于Pytorch实现图像分类——基于jupyter

分类任务 网络基本构建与训练方法,常用函数解torch.nn.functional模块nn.Module模块 MNIST数据集下载 from pathlib import Path import requestsDATA_PATH Path("data") PATH DATA_PATH / "mnist"PATH.mkdir(parentsTrue, exist_okTrue)U…

CSS核心样式-03-浮动+背景属性

目录 五、标准文档流 1. 微观现象 ①空白折叠现象 ②文字类的元素如果排在一行会出现一种高低不齐、底边对齐效果 ③自动换行 2. 元素等级 ①块级元素 ②行内元素 ③ 行内块元素 六、显示模式 display display四个属性值 脱离标准流 七、浮动属性(脱标…

超越传统Lambda函数:深入解析Out-of-line Lambdas的奇妙之处

超越传统函数:深入解析线外 Lambda函数 的奇妙之处 一、背景二、lambda 的捕获三、可能出现的警告四、lambda的广义捕获五、为每种情况进行重载六、总结 一、背景 Out-of-line Lambdas翻译过来就是“线外Lambda函数”或“离线Lambda函数”。Lambda 是使代码更具表现…