笔记 | 编译原理L1
重点关注过程式程序设计语言编译程序的构造原理和技术
1 程序设计语言
1.1 依据不同范型
| 过程式(Procedural programming languages–imperative) | 函数式(Functional programming languages–declarative) | 逻辑式(Logical programming languages–declarative) | 对象式(Object-oriented programming languages) |
|---|---|---|---|
| 程序中指明如何完成一个计算任务 | 程序中指明要进行哪些计算 | 事实+推理规则 | 支持面向对象编程 |
| FORTRAN, PASCAL, C | LISP, HASKELL, ML, OCAML, SCALA… | PROLOG | Smalltalk, Java, C++, Eiffel, Ruby |
| 说明式语言(Declarative programming): 与上述命令式(Imperative language) 不同,没有控制结构,甚至没有赋值,仅有问题说明,或者 说纯数学定义 |
1.2 依据不同转化方式
| 编译型语言 | 解释型语言 | 混合型语言 |
|---|---|---|
| 需通过编译器(compiler)将源代码编译成机器码,之后才能执行的语言。一般需经过编译(compile)、链接(linker)这两个步骤。编译是把源代码编译成机器码,链接是把各个模块的机器码和依赖库串连起来生成可执行文件。 | 不需要编译,相比编译型语言省了道工序,解释性语言在运行程序的时候才逐行翻译。 | 比如C#,C#在编译的时候不是直接编译成机器码而是中间码,.NET平台提供了中间语言运行库运行中间码,中间语言运行库类似于Java虚拟机。.net在编译成IL代码后,保存在dll中,首次运行时由JIT在编译成机器码缓存在内存中,下次直接执行(博友回复指出)。 |
| 优点:编译器一般会有预编译的过程对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高。可以脱离语言环境独立运行。 | 优点:有良好的平台兼容性,在任何环境中都可以运行,前提是安装了解释器(虚拟机)。灵活,修改代码的时候直接修改就可以,可以快速部署,不用停机维护。 | |
| 缺点:编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。 | 缺点:每次运行的时候都要解释一遍,性能上不如编译型语言。 | |
| 代表语言:C、C++、Pascal、swift | 代表语言:JavaScript、Python、Erlang、PHP、Perl、Ruby | Java先生成字节码再在Java虚拟机中解释执行。 |
不同的程序设计语言机制(函数式、过程式、逻辑式、对象式),需要采用不同的技术编写编译程序,过程式语言的编译是对象式语言编译的基础
1.3 另一种角度
| 动态类型语言(Dynamically Typed Language) | 静态类型语言(Statically Typed) | 强类型定义语言(Explicit type) | 弱类型定义语言(Implicit type) |
|---|---|---|---|
| 编译时不知道变量类型,运行时才决定,类型错误属于运行错误,运行时报错 | 编译时候决定变量,类型错误属于语法错误,编译器报错 | 偏向于不容忍隐式类型转换 | 偏向于容忍隐式类型转换 |

2 编译器概述
编译器(Compiler) 将某种语言(源语言)编写的程序翻译成语义等价的另一种语言(目标语言)编写的程序

依据目标程序的类型:
| 目标程序若是可执行的机器语言程序 | 目标程序若是汇编语言的程序 |
|---|---|
可以被用户调用,处理输入并产生输出。![]() | 则须经汇编器汇编后方可执行 |
编译器的重要任务之一是报告它在翻译过程中发现的源程序中的错误。
2.1 编译器的翻译包括哪些步骤
- 阅读并理解程序
- 准确地确定需要采取什么行动
- 弄清楚如何忠实地执行这些行动
- 指示计算机执行这些步骤
[[编译器概述.excalidraw|示例图]]

2.2 编译程序的伙伴程序
| 编辑器 (editor) | 预处理器(preprocessor) | 汇编程序(assembler) | 连接程序(linker) | 装入程序(loader) |
|---|---|---|---|---|
| 除一般的文本编辑功能外,还可以对正在编辑的文本进行分析、提示、自动提供关键字匹配等功能; | 删除源程序中的注释、执行宏替换以及包含文件的嵌入等 | 将编译程序生成的汇编代码汇编成机器代码 | 将不同的目标文件连接到一个可执行的文件中 | 将程序加载到内存中以便执行 |
![]() |
3 编译器的组成
3.1 自然语言翻译过程总结
掌握源语言和目标语言:词法、语法和语义, 翻译过程包括:
| 分析源句子是否正确 | 将句子翻译成目标语言 |
|---|---|
| 拼写,包括识别单词及其属性,依据源语言的语法建立语法结构,检查句子是否有意义 | 翻译每个语法部分,将其组合成有意义的目标语言句子 |
3.2 编译器组成模块

[!Note]- 分析部分
- 源程序 - 语法结构 - 中间表示
- 搜集源程序中的相关信息,放入符号表
- 分析、定位程序中可能存在的错误信息(语法、语义错误)
- 又称编译器的前端(front end),是于机器无关的部分
| 符号表管理 | 词法分析/扫描(lexical analysis, scanning) | 语法分析 | 语义分析 |
|---|---|---|---|
| 记录源程序中使用的变量的名字,收集各种属性(名字的存储分配,类型,作用域,过程名字的参数数量、参数类型等等) | 1.读入源程序的字符流,输出有意义的词素(lexeme)。基于词素,产生词法单元token: <token-name, attribute-value> 2.关于token:程序语言处理的最小单位,token-name由语法分析步骤使用,attribute-value指向相应的符号表条目,由语义分析/代码生成步骤使用 | 1.词法分析后,需要得到词素序列的语法结构 2.语法分析/解析(syntax analysis/parsing):sentence是对单词的再次重组,程序设计语言规定了词法单元、语句的重组规则 — >语句的类别. | 使用语法树和符号表中的信息,检查源程序是否满足语言定义的语义约束。同时收集类型信息,用于代码生成。类型检查,类型转换。 |
| 符号表可由编译器的各个步骤使用 | 程序语言规定了单词构成的规则和单词类别![]() | 根据各个词法单元的第一个分量来创建树形中间表示形式。通常是语法树(syntax tree/parse tree),指出了词法单元流的语法结构![]() |
[!Note]- 合成部分
- 根据符号表和中间表示构造目标程序
- 又称编译器的后端(back end),是于机器相关的部分
| 中间代码生成 | 代码优化 | 目标代码生成 |
|---|---|---|
| 根据语义分析的输出,生成类机器语言的中间表示 | 通过对中间代码的分析,改进中间代码,得到更好的目标代码(快、短、能耗低) | 把中间表示形式映射到目标语言:(寄存器的分配,指令选择,内存分配) |
三地址代码:每个指令最多包含三个运算分量![]() | 优化有具体的设计目标![]() | ![]() |
3.3 编译器的趟(Pass)
趟(Pass):以文件为输入输出单位的编译过程的个数,每趟可由一个或若干个步骤构成。就是对源程序或源程序的中间表示形式从头到尾扫描一次,并作加工处理,生成新的中间结果或目标程序。
- 可以词法分析、语法分析、语义分析等阶段各作为单独一趟
- 也可以词法分析作为语法分析的子程序
- 还可以整个编译程序一遍扫描完成
与编译器组成模块的关系:前者作为“步骤”是逻辑组织方式,“趟”和具体的实现相关
4 解释器
- 定义:解释器(Interpreter):解释器直接利用用户提供的输入执行源程序中指定的操作。

- 解释过程中若发现错误,则返回修改源程序,修改后重新解释执行。
- 解释器与编译器的区别理解:解释器可以直接输出结果,而编译器最终的输出是一个目标程序,是把一种程序设计语言翻译成另外一种语言,编译器的重要任务之一是报告它在翻译过程中发现的源程序中的错误。
4.1 解释器与编译器的比较

二者比较:
| 相同点 | 区别 |
|---|---|
| 使用相同的实现技术 | 实现机制: 翻译 (程序 to 程序)vs. 解释(指令 to 指令序列) |
二者特点:
| 解释器 | 编译器 |
|---|---|
| 可移植性好,支持交互式程序设计,边解释,边执行,错误诊断效果好 | 效率高,一次编译,多次运行,存储代价小,目标程序的执行速度比解释器快很多 |
二者结合的一种应用:Java
- javac 前端编译器:先编译成字节码(bytecode, .class文件)
- 由JVM解释执行,可移植性好
- JIT即时编译器(just-in-time compiling)
- 为了提高热点代码的执行效率,在运行时虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各层次的优化(判断热点代码的方法:基于采样的热点探测;基于计数器的热点探测)
5 构建(Build),构建工具(Make)与编译的关系
- 代码变成可执行文件,叫做编译(compile)
- 安排编译的顺序,叫做构建(build)
- Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目,实际上任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建,构建规则都写在Makefile, “make [选项][参数]”
6 编译器的实现
编译器的开发代价是非常昂贵的,在可能的情况下,可以将一种语言的程序转换成另一种语言的程序,利用另一种语言的编译器进行编译。
前提条件:两种语言在语法和语义上很近似,或者一种语言是另一种语言的扩展;实例:C++ —> C

相关文章:
笔记 | 编译原理L1
重点关注过程式程序设计语言编译程序的构造原理和技术 1 程序设计语言 1.1 依据不同范型 过程式(Procedural programming languages–imperative)函数式(Functional programming languages–declarative)逻辑式(Logical programming languages–declarative)对象式(Object-or…...
k8s存储卷 PV与PVC 理论学习
介绍 存储的管理是一个与计算实例的管理完全不同的问题。PersistentVolume 子系统为用户和管理员提供了一组 API,将存储如何制备的细节从其如何被使用中抽象出来。为了实现这点,我们引入了两个新的 API 资源:PersistentVolume 和 Persistent…...
【WPF应用32】WPF中的DataGrid控件详解与示例
在WPF(Windows Presentation Foundation)开发中,DataGrid控件是一个强大的数据绑定工具,它以表格的形式展示数据,并支持复杂的编辑、排序、过滤和分组等操作。在本文中,我们将详细介绍DataGrid控件的功能、…...
numpy,matplotilib学习(菜鸟教程)
所有内容均来自于: NumPy 教程 | 菜鸟教程 Matplotlib 教程 | 菜鸟教程 numpy模块 numpy.nditer NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。 for x in np.nditer(a, orderF):Fortran order,即是列序优先&#x…...
Web API(四)之日期对象节点操作js插件重绘和回流
Web API(四)之日期对象&节点操作&js插件&重绘和回流 日期对象实例化方法时间戳DOM 节点插入节点删除节点查找节点父子关系兄弟关系M端事件js插件重绘和回流进一步学习 DOM 相关知识,实现可交互的网页特效 能够插入、删除和替换元素节点能够依据元素节点关系查找…...
27.WEB渗透测试-数据传输与加解密(1)
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:26.WEB渗透测试-BurpSuite(五) BP抓包网站网址:http:…...
山寨windows
我的目标是能够运行windows 下的大部分PE格式的程序,这一点通过实验已经证明完全是可行的。 PE格式主要有exe dll sys等文件,这三个文件可以用相同的函数解析, 主要有以下段组成, 1、文件头,包含DOS文件头、PE文件头…...
unity工程输出的log在哪里?
在编辑器里进行活动输出的log位置: C:\Users\username\AppData\Local\Unity\Editor\Editor.log ------------------------------------ 已经打包完成,形成的exe运行后的log位置: C:\Users\xxx用户\AppData\LocalLow\xx公司\xx项目...
【力扣】7. 整数反转
7. 整数反转 题目描述 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 假设环境不允许存储 64 位整数(有符号或无符号)。 …...
Android Apk签名算法使用SHA256
Android apk签名算法使用SHA256 本文不介绍复杂的签名过程,说一下Android签名算法使用SHA256。 但是SHA1不是相对安全签名算法,SHA256更加安全一些。 一般大公司才会有这种细致的安全要求。 如何查看apk签名是否是SHA1还是SHA256 1、拿到apk文件&…...
2024.3.13力扣每日一题——最大二进制奇数
2024.3.13 题目来源我的题解方法一 贪心 题目来源 力扣每日一题;题序:2864 我的题解 方法一 贪心 统计1的个数,满足要求的字符串的末尾一位一定是1,所以需要将一位1放到末尾,然后将剩余的1从最高位开始放࿰…...
2024.4.1力扣每日一题——故障键盘
2024.4.1 题目来源我的题解方法一 直接利用StringBuilder的反转函数方法二 字符数组 题目来源 力扣每日一题;题序:2810 我的题解 方法一 直接利用StringBuilder的反转函数 使用StringBuilder构造结果,并利用其反转函数进行翻转 时间复杂度…...
第十四届蓝桥杯C/C++大学B组题解(一)
1、日期统计 #include <bits/stdc.h> using namespace std; int main() {int array[100] {5, 6, 8, 6, 9, 1, 6, 1, 2, 4, 9, 1, 9, 8, 2, 3, 6, 4, 7, 7,5, 9, 5, 0, 3, 8, 7, 5, 8, 1, 5, 8, 6, 1, 8, 3, 0, 3, 7, 9,2, 7, 0, 5, 8, 8, 5, 7, 0, 9, 9, 1, 9, 4, 4, 6,…...
4.网络编程-websocket(golang)
目录 什么是websocket golang中使用websocket Server端 Client端 什么是websocket WebSocket是一种在互联网上提供全双工通信的协议,即允许服务器和客户端之间进行双向实时通信的网络技术。它是作为HTML5的一部分标准化的,旨在解决传统HTTP协议在实…...
docker安装部署mysql后忘记root密码
应用场景是:用docker安装完mysql后,使用安装时候设置的密码登录不上MySQL; 1、修改docker映射出mysql的配置文件:my.cnf 在mysqld最下方添加skip-grant-tables进入安全模式(随意一个密码即可登录mysql) [m…...
c++的学习之路:14、list(1)
本章讲一下如何使用list,代码在文章末 目录 一、list介绍 二、增 三、删 四、查和改 五、交换 六、代码 一、list介绍 首先还是看一看官方文档的介绍如下图,如下方五点: 1. list是可以在常数范围内在任意位置进行插入和删除的序列式…...
huawei 华为交换机 配置 VLAN 聚合示例
组网需求 某公司拥有多个部门且位于同一网段,为了提升业务安全性,将不同部门的用户划分到不同VLAN 中,如 图 5-7 所示, VLAN2 和 VLAN3 属于不同部门。各部门均有访问Internet需求,同时由于业务需要,不同部…...
【QT+QGIS跨平台编译】056:【pdal-dimbuilder+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
点击查看专栏目录 文章目录 一、pdal介绍二、dimbuilder介绍三、pdal下载四、文件分析五、pro文件六、编译实践七、生成Dimension.hpp八、生成pdal_features.hpp一、pdal介绍 PDAL(Point Data Abstraction Library)是一个开源库,用于处理点云数据的获取、过滤、转换、分析和…...
【Python】探索Python中的aiohttp:构建高效并发爬虫
后来 我总算学会了 如何去爱 可惜你 早已远去 消失在人海 后来 终于在眼泪中明白 有些人 一旦错过就不再 🎵 HouZ/杨晓雨TuTu《后来》 在数据密集和网络密集的任务中,提高程序的执行效率是非常重要的。Python作为一门强大的编程语言…...
创建真实项目vue2项目
1. 创建 vue create 项目名 2. 选择自定义 3. 勾选以下必备选项 4.选择使用vue2 5. 选择哈希模式(n); css选择Less 6. ESLint校验 选择 7. 保存(按照默认) 8. 在哪里添加ESLint文件 9. 要不要把这个改成将来的预设&am…...
Vivado里写状态机总出警告?聊聊三段式、二段式的选择与那些让人头疼的Latch和Combinatorial Loop
Vivado状态机设计实战:从三段式优化到Latch消除全攻略 状态机设计中的典型痛点与EDA工具特性 第一次在Vivado中看到"Inferring Latch"警告时,我盯着综合报告发了半小时呆——明明代码逻辑完全正确,为什么工具非要"自作主张&qu…...
aivectormemory:轻量级向量记忆库,为AI应用开发提供灵活存储方案
1. 项目概述:向量记忆库的“新玩家”最近在折腾AI应用开发,特别是涉及到需要让模型“记住”大量私有知识或者进行复杂对话的场景时,一个绕不开的核心组件就是向量数据库。大家熟知的Pinecone、Weaviate、Milvus这些方案固然强大,但…...
从零搭建高效AI协作工作流,NotebookLM团队空间配置、知识对齐与冲突消解全链路实操手册
更多请点击: https://intelliparadigm.com 第一章:NotebookLM团队协作功能概览 NotebookLM 是 Google 推出的基于 LLM 的研究型笔记工具,其团队协作能力围绕“共享上下文、实时协同、权限精细化”三大核心设计。当多个成员加入同一 Notebook…...
STM32F103C8T6连接移远EC200N-CN 4G模块:从硬件接线到TCP透传的保姆级避坑指南
STM32F103C8T6与移远EC200N-CN 4G模块深度开发实战 在物联网终端设备开发中,稳定可靠的网络连接是实现远程数据交互的核心基础。本文将详细介绍如何基于STM32F103C8T6微控制器与移远EC200N-CN 4G Cat.1模块构建完整的联网解决方案,涵盖硬件设计、AT指令交…...
书成紫微动律定凤凰驯:抛开网络臆想歪论正视海棠山铁哥的大道凰标之道
——褪去网络流言,正视正统文脉网络世间众说纷纭,流言四起,诸多无根揣测、片面臆想肆意流传。 不少人未曾静心品读深意,仅凭只言片语便妄加评判,或是跟风曲解本意,或是刻意附会杂论,更有甚者凭空…...
基于ARM嵌入式平台与AI视觉的输电线路智能巡检系统设计与实现
1. 项目概述:输电线路巡检的智能化转型 输电线路作为电力系统的“大动脉”,其安全稳定运行至关重要。传统的线路巡检主要依赖人工,巡检人员需要跋山涉水,通过望远镜、红外测温仪等设备进行观测和记录。这种方式不仅劳动强度大、效…...
AI智能体集群如何革新代码审查:架构、实现与CI/CD集成
1. 项目概述:一个为代码审查提效的智能体集群如果你是一名团队的技术负责人或资深开发者,肯定对代码审查(Code Review)这个环节又爱又恨。爱的是,它是保证代码质量、促进知识共享的关键闸门;恨的是…...
基于本体论的技能知识图谱:从理论到工程实践
1. 项目概述:当技能遇上本体论最近在整理个人知识库和团队技能矩阵时,我遇到了一个老生常谈的难题:如何用一种结构化的、机器可读的方式,清晰地定义和关联“技能”这个概念?我们通常用Excel表格、标签云或者简单的列表…...
告别手动!用Allegro Testprep脚本批量处理测试点,效率提升200%
Allegro Testprep脚本自动化:高密度PCB测试点优化实战指南 在高速PCB设计领域,测试点布局常常成为制约项目进度的隐形瓶颈。当面对超过500个网络的高密度主板时,传统手动调整测试点的方式会让工程师陷入无尽的重复劳动——据统计,…...








