17.1.2 编译程序与解释程序
编译程序和解释程序都属于语言处理程序,都要理解源程序的词法、语法和语义。它们真正的分界点不在“有没有分析源代码”,而在“是否生成可独立执行的目标程序,以及运行时处理程序是否还要参与”。
两种路线
mermaid
flowchart TB
subgraph C["编译方式"]
A1["源程序"] --> B1["编译程序"]
B1 --> C1["目标程序"]
C1 --> D1["执行"]
end
subgraph I["解释方式"]
A2["源程序"] --> B2["解释程序"]
B2 --> D2["边解释边执行"]
end| 维度 | 编译程序 | 解释程序 |
|---|---|---|
| 处理方式 | 先把源程序翻译成目标程序 | 运行时逐句或逐段解释执行 |
| 是否生成目标程序 | 通常生成 | 通常不生成独立目标程序 |
| 运行时是否需要处理程序 | 目标程序执行时不需要编译程序参与 | 需要解释程序参与 |
| 执行效率 | 一般较高 | 一般较低 |
| 灵活性 | 修改后通常要重新编译 | 交互、调试和跨平台更灵活 |
| 移植性 | 与目标平台、编译器相关 | 依赖解释器或虚拟机,常更易跨平台 |
共同点:都要“读懂”程序
课程里提醒过,解释程序并不是完全绕过编译原理。无论编译还是解释,都需要词法分析、语法分析和语义分析。差别在于分析之后怎样执行:编译器把结果生成目标代码,解释器把结果直接驱动运行。
技术演进:纯编译、纯解释到混合模式
早期教材常把 C 归为编译型,把 Python 归为解释型,把 Java 说成解释执行。现代实现更复杂,例如 Java 源程序先编译成字节码,再由 JVM 解释或即时编译执行。考试通常按教材分类作答,但理解时要知道“编译/解释”是实现路线,不是语言天生不可改变的属性。
| 路线 | 为什么被采用 | 优势 | 局限 |
|---|---|---|---|
| 静态编译到机器码 | 追求运行效率和部署独立性 | 执行快,运行时依赖少 | 跨平台需要重新编译 |
| 解释执行 | 追求交互性和灵活性 | 调试方便,部署简单 | 每次运行都有解释开销 |
| 字节码 + 虚拟机 | 兼顾跨平台和性能 | 一次编译,多平台运行,可 JIT 优化 | 依赖虚拟机,启动和内存成本较高 |
高频判断
题干说“源程序经编译后形成目标程序,目标程序可独立运行”,选编译。题干说“解释程序在用户程序运行时参与,边翻译边执行”,选解释。题干问“执行用户程序时编译程序是否参与”,答案通常是不参与;解释程序则参与。
小练习
题:编译程序和解释程序都可能进行词法、语法、语义分析吗?
答:可能。二者都需要理解源程序,只是后续执行方式不同。
自查
- 为什么“是否生成目标程序”是区分编译与解释的关键?
- 编译型语言执行效率通常更高的原因是什么?
- Java 这类字节码语言为什么不能简单理解为纯编译或纯解释?