A Complete Guide to Program Compilation and Execution | 程序编译与运行机制考点解读

📚 A Complete Guide to Program Compilation and Execution | 程序编译与运行机制考点解读

Program compilation and execution form the foundation of computer science. Every program you write must be translated into machine code before it can run on a CPU. Understanding this process is not just about memorising steps — it is about grasping how hardware and software interact, and this understanding is frequently tested in exams.

程序编译与运行机制是计算机科学的基石。你编写的每一条程序,都必须被翻译成机器码后才能交给 CPU 执行。理解这一流程,不只是为了背出几个步骤——而是要真正掌握软硬件之间如何协作。这正是考试命题的高频切入点。


1. Why Compilation Is a Core Exam Topic | 为什么编译机制是核心考点

Examiners love compilation because it links multiple syllabus areas: programming, computer architecture, operating systems, and even data structures. A single question can test your ability to trace a variable through lexical analysis, see how syntax errors are caught, and explain why linked libraries are loaded at runtime.

命题人青睐编译机制,是因为它能串联多个大纲板块:程序设计、计算机体系结构、操作系统,乃至数据结构。一道题就能综合考查你能否追踪一个变量如何通过词法分析、判断语法错误如何被发现、以及解释链接库为何在运行时才被载入内存。

Moreover, compilers are deterministic. There is no ambiguity in the correct answer, which makes them ideal for written exams. Students who understand each stage clearly can quickly eliminate wrong options in multiple-choice questions and structure solid long-answer responses.

此外,编译过程是确定性的。答案不存在模棱两可的空间,因此非常适合书面考试。透彻理解每个阶段的学生,能在单选题中快速排除错误选项,也能在简答题中写出结构严谨的答案。


2. What Is a Compiler | 编译器是什么

A compiler is a program that translates source code written in a high-level language, such as C or Python (via a compiler backend), into a lower-level representation, typically machine code or bytecode. The key property of a compiler is that translation happens before execution, producing an executable file that can run independently.

编译器是一种程序,它将用高级语言(如 C,或 Python 的编译后端)编写的源代码,翻译为更低层的表示形式,通常是机器码或字节码。编译器最关键的属性是:翻译发生在执行之前,最终产出一个可独立运行的可执行文件。

Source Code → Compiler → Object Code → Linker → Executable File

This contrasts with an interpreter, which translates and executes statements one at a time. Understanding this distinction is essential because it affects program speed, error detection timing, and portability.

这与解释器形成对比——解释器逐条翻译并执行语句。理解二者的区别至关重要,因为它影响程序运行速度、错误发现时机以及可移植性。


3. The Six Stages of Compilation | 编译的六大阶段

Classical compilation is commonly divided into six stages. You must be able to list them in order and explain what each one does. The order is fixed and cannot be re-arranged — this is one of the most frequently tested facts in the syllabus.

经典编译流程通常分为六个阶段。你必须能够按顺序列出它们,并解释每个阶段的功能。这个顺序是固定的,不可随意调换——这是大纲中最常考查的知识点之一。

Stage Key Output Common Errors Caught
1. Lexical Analysis Tokens Illegal characters
2. Syntax Analysis Parse Tree Missing semicolons, mismatched brackets
3. Semantic Analysis Annotated Parse Tree Type mismatches, undeclared variables
4. Intermediate Code Generation Three-address Code N/A (internal)
5. Optimization Optimized Intermediate Code N/A (improves speed)
6. Code Generation Object / Machine Code N/A

Note that in many exam boards, the preprocessing stage is included as an extra step before lexical analysis, especially when C is used as the reference language. We will discuss preprocessing in the next section.

请注意,许多考试局在词法分析之前还会包含一步预处理,尤其是在以 C 语言为参考语言时。我们将在下一节讨论预处理。


4. Preprocessing and Lexical Analysis | 预处理与词法分析

In languages like C, the first practical step is preprocessing. The preprocessor handles directives such as #include, #define, and conditional compilation. It replaces macros and inserts the content of header files, producing a “pure” source stream that the compiler can process.

在 C 这类语言中,实际的第一步是预处理。预处理器处理 #include#define 以及条件编译等指令。它将宏展开、将头文件内容插入源码,生成一个编译器可处理的”纯净”源文件流。

After preprocessing, lexical analysis (also called scanning) reads the source character by character and groups them into meaningful sequences called tokens. Tokens include keywords like if, while, identifiers like count, operators like + and <=, and literals like 42 or "hello".

预处理之后,词法分析(也称扫描)逐字符读取源文件,将字符组合为有意义的序列,称为记号。记号包括 ifwhile 等关键字,count 等标识符,+<= 等运算符,以及 42"hello" 等字面量。

A common error caught in this stage is the “illegal character” error. For example, typing the currency symbol £ inside a C program where the compiler does not expect it will cause the lexical analyser to reject the input. The output of lexical analysis is a token stream — a flat sequence that is passed to the next stage.

此阶段最常见的错误是”非法字符”错误。例如,在 C 程序中输入编译器不期望的货币符号 £,词法分析器会拒绝该输入。词法分析的输出是记号流——一个扁平的序列,传递给下一阶段。


5. Syntax Analysis and Parse Trees | 语法分析与语法树

Syntax analysis (also called parsing) takes the token stream and checks whether the sequence of tokens conforms to the grammar of the programming language. The grammar is typically expressed in Backus-Naur Form (BNF) or a variant. If the tokens form a valid sentence in the language, the parser builds a parse tree (also known as a syntax tree).

语法分析(也称解析)接收记号流,检查记号序列是否符合该程序语言的文法。文法通常用巴科斯-瑙尔范式(BNF)或其变体来描述。如果记号在该语言中构成合法的”句子”,解析器就构建一棵语法树(也称作语法分析树)。

Token Stream → Parse Tree (or Syntax Error → Recovery)

Examiners often ask which errors are caught in this stage. Classic examples include: missing semicolons, unbalanced parentheses, and using a keyword in the wrong position. A parse tree represents the grammatical structure but does not yet check whether the operations make sense. For example, int x = "hello" + 3; is syntactically valid in many compiled languages, but semantically wrong.

考官常问哪些错误在本阶段被捕获。典型例子包括:缺少分号、括号不匹配、关键字使用位置不当。语法树表达的是语法结构,但还不检查操作是否有意义。例如 int x = "hello" + 3; 在许多编译型语言中语法正确,但在语义上却是错误的。

Many exam questions will show a short code snippet and ask you to identify whether the error would be detected during lexical, syntax, or semantic analysis. The key is to remember: lexical errors involve bad symbols; syntax errors involve bad structure; semantic errors involve bad meaning.

许多考题会展示一小段代码,问你在词法、语法还是语义分析阶段能发现错误。关键记忆点是:词法错误涉及非法符号;语法错误涉及结构不正确;语义错误涉及含义不正确。


6. Semantic Analysis | 语义分析

Semantic analysis ensures that the program is meaningful. It checks type compatibility, variable declarations, function signatures, and whether operators are applied to valid operands. This stage commonly produces an annotated parse tree, where each node has type information attached.

语义分析确保程序具备合理的含义。它检查类型兼容性、变量声明、函数签名,以及运算符是否作用于合法的操作数。该阶段通常生成一棵带标注的语法树,每个节点上都附有类型信息。

For example, consider the expression a + b. The semantic analyser looks up the declarations of a and b in the symbol table. If a is an integer and b is a string, the analyser may insert an implicit type conversion, or it may issue an error such as “incompatible types”.

例如,考虑表达式 a + b。语义分析器在符号表中查找 ab 的声明。如果 a 是整型而 b 是字符串,分析器要么插入隐式类型转换,要么报错,如”类型不兼容”。

The symbol table is a crucial data structure used in this stage. It stores every identifier, its type, its scope, and its memory location (which may be assigned later). Understanding the symbol table helps students answer questions about variable shadowing and scoping rules.

符号表是本阶段使用的核心数据结构。它保存每个标识符、其类型、作用域以及(稍后分配的)内存位置。理解符号表有助于学生回答关于变量遮蔽(shadowing)和作用域规则的问题。


7. Intermediate Code and Optimization | 中间代码与优化

After semantic analysis, the compiler generates intermediate code — a platform-independent representation. A well-known form is three-address code, where each instruction has at most three operands. For example, the expression x = a + b * c might be translated into two instructions:

语义分析之后,编译器生成中间代码——一种与平台无关的表示方式。常见形式是三地址码,其中每条指令最多包含三个操作数。例如,表达式 x = a + b * c 可被转换为两条指令:

t₁ = b * c
x = a + t₁

Using intermediate code makes the compiler more portable. Only the final code generation stage needs to be rewritten for each target machine. It also simplifies optimization, because the same optimizations can be applied to the intermediate code regardless of the source language.

使用中间代码使得编译器更具可移植性。只有最终的代码生成阶段需要针对不同目标机器重写。它还简化了优化,因为无论源语言是什么,都可以对同一份中间代码应用相同的优化方法。

Optimization aims to improve speed, reduce memory usage, or both. Common techniques include constant folding (computing 2 + 3 at compile time to produce 5), dead code elimination (removing statements that never execute), and loop unrolling. Exam questions may ask you to apply a simple optimization to a short snippet or to identify which optimization technique was used.

优化旨在提升速度、降低内存占用,或两者兼得。常见技术包括常量折叠(编译时计算 2 + 3 得到 5)、死代码消除(删除永不执行的语句)、以及循环展开。考题可能要求你对一小段代码应用简单优化,或者判断使用了哪种优化技术。


8. Code Generation and Object Code | 代码生成与目标代码

Code generation is the stage where the optimized intermediate code is translated into assembly language or directly into machine code specific to the target processor architecture. For example, a compiler targeting an Arm processor produces different instructions than one targeting an x86 processor for the same source code.

代码生成阶段将优化后的中间代码翻译为汇编语言,或直接翻译为针对目标处理器架构的机器码。例如,针对 Arm 处理器的编译器与针对 x86 处理器的编译器,为同一源代码生成的指令是不同的。

The output of this stage is an object file (often with .o or .obj extension). An object file contains machine code plus metadata such as symbol tables and relocation information. However, an object file is not yet executable — it may contain unresolved references to functions defined in other files or libraries.

这一阶段的输出是目标文件(通常以 .o.obj 为扩展名)。目标文件包含机器代码以及符号表、重定位信息等元数据。但目标文件还不能直接运行——它可能包含对其它文件或库中函数的未解析引用。

Linking is the final step that combines multiple object files and libraries into a single executable. This step resolves external references, assigns final memory addresses, and produces the executable file. On modern operating systems, linking can be static (all library code is copied into the executable) or dynamic (the executable refers to shared libraries loaded at runtime).

链接是将多个目标文件和库合并为单个可执行文件的最后一步。它解析外部引用、分配最终内存地址、生成可执行文件。在现代操作系统中,链接可以是静态链接(所有库代码被复制进可执行文件)或动态链接(可执行文件引用运行时加载的共享库)。


9. Runtime Execution and Memory Layout | 运行时与内存布局

When a program is executed, the operating system loads the executable into memory. The memory for a running process is typically divided into four segments: text (machine code), data (initialized and uninitialized globals), heap (dynamically allocated memory), and stack (function call frames and local variables).

程序被执行时,操作系统将可执行文件载入内存。一个运行中进程的内存通常划分为四个段:代码段(机器代码)、数据段(已初始化和未初始化的全局变量)、(动态分配的内存)以及(函数调用帧和局部变量)。

Stack → (grows down) ← Heap (grows up) → Data → Text

Exam questions often ask where a particular variable is stored. Global variables go to the data segment; local variables go to the stack; memory allocated with malloc or new goes to the heap. The program counter (PC) in the CPU holds the address of the next instruction to be fetched from the text segment.

考题经常问某个变量存储在哪个区域。全局变量存入数据段;局部变量存入栈;用 mallocnew 分配的内存存入堆。CPU 的程序计数器(PC)保存着即将从代码段取出的下一条指令的地址。

One subtle point: in real systems, the stack grows downward and the heap grows upward, which allows them to share the available address space flexibly. A stack overflow occurs when the stack grows past the heap boundary, often due to unbounded recursion.

一个容易忽略的要点是:实际系统中栈向下增长、堆向上增长,这样二者可以灵活共享可用地址空间。当栈越界与堆相撞时会发生栈溢出,通常由无界递归导致。


10. Compilation vs Interpretation vs JIT | 编译、解释与JIT对比

Students often mix up compilers, interpreters, and just-in-time (JIT) compilers. A compiler translates the entire program before execution. An interpreter translates and runs the program statement by statement. A JIT compiler converts bytecode (for example, Java bytecode or Python .pyc files) into machine code at runtime, just before execution.

学生经常混淆编译器、解释器和即时(JIT)编译器。编译器在执行前翻译整个程序。解释器逐句翻译并运行程序。JIT 编译器在运行时、即将执行之前,将字节码(如 Java 字节码或 Python 的 .pyc 文件)转换为机器码。

Feature Compiler Interpreter JIT
Translation timing Before execution During execution During execution
Execution speed Fast Slow Fast (after warm-up)
Error detection All at compile time At runtime, up to failing line Mixed
Portability Needs recompilation High (source travels) High (bytecode travels)

An important exam point is that interpreted languages often run slower because the interpreter itself is an extra layer of software that analyses each statement during execution. However, they offer greater flexibility and easier debugging because errors are reported with exact line numbers as they happen.

一个重要的考点是:解释型语言通常运行更慢,因为解释器本身是额外的一层软件,在运行时逐条分析语句。然而,它们提供了更高的灵活性和更易调试的优点,因为错误发生时能精确报出行号。

Python is particularly interesting: it is compiled to bytecode by a compile step (producing .pyc files), then the bytecode is executed by the CPython interpreter — and in some implementations, a JIT compiles frequently used functions on the fly. Exam boards often simplify this, so follow the model your syllabus describes.

Python 特别有趣:它先由编译步骤生成字节码(产生 .pyc 文件),随后字节码由 CPython 解释器执行——而在某些实现中,JIT 会即时编译频繁调用的函数。考试局通常会简化这一点,请遵循你大纲所描述的基本模型。


11. Common Pitfalls in Exam Questions | 常见易错点

The first common pitfall is confusing compile-time errors with runtime errors. Division by zero, array index out of bounds, and dereferencing a null pointer are runtime errors — the compiler will not catch them. Only errors such as a missing semicolon, undeclared identifier, or wrong type are compile-time errors.

第一个易错点是混淆编译时错误运行时错误。除零、数组越界、解引用空指针都是运行时错误——编译器不会捕获它们。只有像缺少分号、未声明标识符、类型错误等才是编译时错误。

The second pitfall is forgetting that the linker is separate from the compiler. An error like “undefined reference to `function`” appears at link time, not compile time. Even if every file compiles perfectly, linking can fail if a function is declared but never defined.

第二个易错点是忘记链接器与编译器是分开的。”对 `function` 的未定义引用”这类错误出现在链接阶段,而非编译阶段。即使每个文件都编译完美,如果某个函数只声明而未定义,链接仍会失败。

The third pitfall concerns the order of stages. Some students try to optimise code before performing semantic analysis. That is incorrect — the compiler must understand the meaning first. Always remember the rigid sequence: preprocessing → lexical → syntax → semantic → intermediate code → optimization → code generation → linking.

第三个易错点是关于阶段顺序。有些学生试图在语义分析之前就进行优化。这是不对的——编译器必须先理解程序的含义。务必牢记严格的顺序:预处理 → 词法 → 语法 → 语义 → 中间代码 → 优化 → 代码生成 → 链接。


12. Study Strategies and Final Tips | 备考策略与最终建议

To master this topic, first create a one-page flowchart showing all compilation stages with their inputs and outputs. Then for each stage, memorise two example errors it detects and one example of its output. This gives you a solid answer skeleton for any long-form question.

要掌握这个专题,首先画一张单页流程图,展示所有编译阶段及其输入和输出。然后对每个阶段,记住两个它能发现的错误示例以及一个输出示例。这会为任何简答题提供扎实的答题骨架。

Secondly, practise tracing short code snippets through each stage. Write a tiny program, then write down what the token stream looks like, draw a partial parse tree, and list which identifiers go into the symbol table. This kind of hands-on revision is far more effective than merely reading.

其次,练习把每段小代码逐阶段追踪一遍。写一个小程序,然后写下它的记号流长什么样、绘制部分语法树、列出哪些标识符进入符号表。这种动手式复习远比为阅读而阅读有效得多。

Finally, when answering exam questions, always use the correct terminology: “lexical analysis”, “syntax analysis”, “semantic analysis”, “intermediate code”, “code generation”, and “linking”. Examiners award marks for precise vocabulary. Avoid vague terms like “the computer checks things” — be specific about which “checking” happens at which stage.

最后,回答考题时务必使用准确的术语:”词法分析”、”语法分析”、”语义分析”、”中间代码”、”代码生成”和”链接”。考官会给精确的术语打分。避免使用模糊的表述,如”计算机检查了一些东西”——要具体说明哪一步”检查”发生在哪个阶段。


Published by TutorHao | Computer Science Revision Series | aleveler.com

更多咨询请联系16621398022(同微信)

Comments

屏轩国际教育cambridge primary/secondary checkpoint, cat4, ukiset,ukcat,igcse,alevel,PAT,STEP,MAT, ibdp,ap,ssat,sat,sat2课程辅导,国外大学本科硕士研究生博士课程论文辅导Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from aleveler.com

Subscribe now to keep reading and get access to the full archive.

Continue reading

Exit mobile version