AI 都能替你写代码的今天,很多人敲了三五年键盘,却从没想过一个最基本的问题:你写下的那串字符,计算机是怎么“看懂”的? 编程语言圈有一条长青爆款视频——Frame of Essence 频道的《How do computers read code?》(计算机如何读代码),它用不到五分钟的动画,把编译器与解释器的工作原理讲成了一个人人能懂的“翻译”故事。这条视频常年霸占“编译器入门”相关搜索的前列,累计播放达数百万次,是无数计算机专业学生和自学者接触“语言实现”这个领域的第一课。本文按照视频的叙事顺序逐段拆解,把它省略的工程细节、背后的真实历史与理论全部补齐——没看过视频,你能看懂;看过视频,你能多懂一层。
| 项目 | 内容 |
|---|---|
| 视频标题 | How do computers read code?(计算机如何读代码?) |
| 频道 | Frame of Essence |
| 主题分类 | 编程语言实现 / 编译原理科普 |
| 时长 | 约 4 分钟动画短片 |
| 热度 | 播放达数百万次,是该频道播放量最高的视频之一,长期被各大学课程与论坛引用为编译入门首选 |
※ 说明:本篇撰写环境无法联网实时核对页面,以上播放量与时长为据频道页面的历史数据,请以 YouTube 当前页面为准。
这条视频的全部论证,建立在一个隐喻上:编程语言是人与机器之间的“外语”,读懂代码的本质是翻译。 按叙事顺序,它讲了五件事。
视频开场先立起一个反差:人类写的代码——if、while、变量、函数——在 CPU 眼里毫无意义。CPU 是一台“只听得懂母语”的机器,它的母语是机器码:一串串固定长度的二进制指令,每条指令对应一个极原始的操作,比如“把这个寄存器里的数加一”“把这个地址的数据搬过去”。人类不可能直接用这种语言思考。程序员的创造力靠的是高级语言,而高级语言和机器码之间的鸿沟,必须有人来填——这个“翻译官”,就是视频的主角。
这是全片最经典的段落。视频用“翻译一本书”作比,给出了两种截然不同的策略:
视频明确指出两者的代价结构不同:编译慢在运行前,快在运行时;解释快在启动,慢在执行——因为每次运行都要重新翻译一遍。这个“时间花在哪里”的框架,是理解一切语言性能差异的起点。
接下来是全片技术含量最高的部分:编译器(或解释器)读代码的第一步,词法分析(lexical analysis)。
编译器看到的源代码,最初只是一长串字符。它做的第一件事是“断句分词”:把 int count = 10; 这样的字符流,切成一个个有意义的记号(token)——int 是关键字,count 是标识符,= 是运算符,10 是数字字面量,; 是分隔符。干这活的组件叫词法分析器(lexer / tokenizer)。
视频用了一个精妙的类比:这就像你读一门没学过的外语时,先得知道哪里是一个词的结尾、哪些字符组合构成一个“单词”。空格和换行帮了人类的忙,但对机器来说,它需要明确的规则来判定“这串字符是一个整体”。
第二步,语法分析(parsing)。有了单词还不够——“ count int = 10”打乱顺序就毫无意义。语言之所以是语言,在于单词必须按语法规则组合。语法分析器(parser)拿着一套语法规则,把记号流组装成抽象语法树(Abstract Syntax Tree,AST)。
比如 2 + 3 × 4,解析出来的不是一串平铺的记号,而是一棵树:乘法是根节点,3 和 4 是它的孩子,而整个乘法节点又是加法节点的一个孩子——这棵树的结构,天然编码了“先乘后加”的优先级。视频在这里点破了全片最深的一层认知:代码在机器内部的存在形式不是文本,而是一棵树。 你写的是一行行字符串,机器“想”的却是一棵层级结构。
树建好了,翻译就是水到渠成的事:
ADD 指令,赋值节点翻译成“取数—写入内存”的指令序列。最终输出一份完整的机器码文件。视频的收尾升华了主题:编译器和解释器本质上是同一件事的两种完成度——“把一种语言翻译成另一种语言”。而最有意思的地方在于:翻译官自己也是程序,也是用某种语言写的。这个自指结构,为整个领域埋下了最深的一颗种子。
这条视频是科普浓缩,它背后的每一环都有扎实的工程史与理论支撑。逐环补齐:
“编译器”这个概念的工程起点,通常追溯到格蕾丝·霍珀(Grace Hopper)。1952 年,她在 UNIVAC 上实现了 A-0 编译器——能把人们用助记方式写下的例程描述,翻译成机器可执行的代码。霍珀后来的 FLOW-MATIC 语言(1957)直接催生了商用到今天的 COBOL。她坚持“程序应该用接近英语的方式写、让机器去适应人而不是人适应机器”,这个理念就是“高级语言”的灵魂。今天我们说“编译”,词源上就是霍珀一代人把"compile"(汇编、编纂)从出版业借来用的结果。
1957 年,约翰·巴科斯(John Backus)带领 IBM 团队交付了 FORTRAN 编译器——第一个能生成高效机器码的高级语言编译器。它证明了一件事:机器生成的代码可以比手写汇编更优化,从此“用高级语言写程序”在经济上成立了。巴科斯随后在 ALGOL 58/60 报告中与彼得·瑙尔(Peter Naur)共同确立了 BNF 范式(Backus–Naur Form)——一种用“产生式规则”精确描述语法的方式。视频里“语法规则决定单词怎么组句”,其严格的数学形态就是 BNF。
视频先拆词、再组句的两步走,并非工程直觉,而是语言学理论的直接映射。1956 年,语言学家诺姆·乔姆斯基(Noam Chomsky)发表《Three Models for the Description of Language》,提出著名的乔姆斯基层级,把语言按复杂度分成四层。对编译器设计者最重要的区分是:
一句话:词法用正则,语法用文法——两步走是数学上的必然,不是风格选择。(顺带一提:解析领域后来发展出 LL、LR 等算法族,其中 LR(k) 由高德纳的学生时代论文奠基,即 Donald Knuth 于 1965 年发表的 LR 理论;工程上更常用手写的“递归下降解析器”,现代大量语言的编译器前端都采用它。)
解释执行的谱系从约翰·麦卡锡(John McCarthy)1958 年的 Lisp 开始。Lisp 的代码和数据同构(都是 S 表达式),麦卡锡用半页纸的 eval 函数就定义了整个语言——这是“解释器”概念的理论起点。视频里“解释器照着语法树直接执行”的描述,与 Lisp 的 eval/apply 循环一脉相承。
视频的二分法是教学简化。真实世界的主流引擎几乎全是混合模式:
.pyc,下次免解析;LuaJIT、PyPy 都是解释器加即时编译的组合。还有一个可爱的自指结构值得单独说:自举(bootstrapping)——用 C 语言写 C 的编译器,用 Rust 写 Rust 的编译器。这带来一个著名的深水区问题:肯·汤普森(Ken Thompson,Unix 之父)1984 年图灵奖演讲《Reflections on Trusting Trust》指出:如果编译器本身被植入后门,它可以悄悄把后门“传染”给每一个它编译出来的程序,甚至在编译自己的源码时也看不出来。读代码这件事的信任链,最终要落在“你相信哪个编译器”上——这是视频没讲、但每个系统程序员都该知道的一层。
证据充分的部分:词法分析→语法分析→AST→生成/执行的流水线框架,是教科书级的共识(龙书《Compilers: Principles, Techniques, and Tools》——Aho、Lam、Sethi、Ullman 合著——前几章就是这个结构),没有任何争议。AST 作为“代码的机器内部形态”也完全准确,今天的 ESLint、Prettier、Tree-sitter 全部工作在 AST 上。
被简化的部分需要三点提醒:
int x = "hello"; 能建出一棵树,但类型对不上。真实编译器在 AST 之后还有语义分析(类型检查等)、中间表示和动辄几十上百个优化 pass。视频跳过了从“正确的树”到“高效的机器码”之间最难、也最值钱的部分——这没问题,但读者要知道那才是编译器工程的大头。另有一个真实的工程争议可以补充:语法本身也是复杂性来源。C++ 的模板语法让“拆词建树”变得病态困难(尖括号既可能是比较运算符又可能是模板括号,需要语义信息才能定论),以至于 C++ 编译器前端常年是最难写的软件之一——这是“上下文无关”在实践中被打破的著名案例。
第一,把编译器错误信息当成你的第一次 code review。 理解了流水线,你就知道错误信息的层级:unexpected character 是词法层在说话,expected ';' 是语法层在说话,type mismatch 是语义层在说话。读懂报错属于哪一层,定位速度立刻翻倍——报错发生在哪一步,问题就大致出在哪一段。
第二,学会用“代码即树”的视角做自动化。 既然代码在机器里是 AST,那么批量改代码的正道就是操作 AST 而不是正则替换:ESLint 规则、Prettier 格式化、各大厂的 codemod 迁移工具,本质都是“遍历语法树、改节点、再打印回去”。下次想对代码库做大规模修改时,先想想“这能不能在语法树上做”,而不是硬写正则。
第三,动手写一个 200 行的迷你解释器。 这是消化这条视频最狠的方式。Bob Nystrom 的免费在线书《Crafting Interpreters》会带你用不到千行代码写出一个能跑的 LISP 方言与脚本语言; Thorsten Ball 的《Writing an Interpreter in Go》是另一条常被推荐的路径。写完拆词和建树,你会对“代码是什么”产生永久性的认知升级——从此你看任何语言,看到的都不再是字符,而是树。
flowchart TD
A[人写高级语言] --> B[机器只懂机器码]
B --> C[需要翻译官]
C --> D{翻译哲学二选一}
D --> E[编译器<br/>先整本翻译]
D --> F[解释器<br/>边读边执行]
E --> G[第一步 词法分析<br/>字符切成记号]
F --> G
G --> H[第二步 语法分析<br/>记号拼成语法树]
H --> I[编译路线<br/>遍历树生成机器码]
H --> J[解释路线<br/>照着树直接执行]
I --> K[产物可反复运行]
J --> L[每次运行重复翻译]
K --> M[翻译官也是程序<br/>自举与信任链]
L --> M
这条视频最了不起的地方,是用四分钟把“编译原理”从一门劝退课变成了一次顿悟:读代码和读文章,遵循同样的语言学规律;而读懂代码的那个翻译官,本身也是一段被翻译出来的代码。 在 AI 代写代码的时代,“代码如何被读懂”这个问题有了新的分量——机器读得越来越懂,人反而更需要理解读代码的机制本身。看完视频再回头看本文补上的那些名字:霍珀、巴科斯、乔姆斯基、麦卡锡、拉特纳——你会发现,这四分钟动画里,压缩着七十年语言实现史的全部主干。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
