COMPUTER SCIENCE · AN OVERVIEW · CHAPTER 6

程序设计语言

PROGRAMMING LANGUAGES

第 5 章用伪代码描述算法——本章把伪代码升级为真正的语言:让人读得懂,也让机器跑得了。从 0/1 到对象,语言层次的每一次跃升,都让“人想出的办法”更容易变成“机器能执行的程序”。

《计算机科学概论》(第 13 版) J. Glenn Brookshear | 大学一年级 · 教学页
机器语言 · 汇编语言 · 高级语言 · 范型 · 变量与类型 · 函数 · 翻译 · 面向对象
程序设计语言的三代演变:机器语言、汇编语言与高级语言
CHAPTER 6 · LEARNING MAP

本章学习地图

每节末尾附“本节小结”;每节配 2 道课堂选择题(A/B/C/D),共 10 题,参考答案见页面底部。

小节核心问题关键概念
6.1 历史回顾语言如何从 0/1 进化到接近人类语言?机器/汇编/高级语言 · 翻译器 · 四大范型
6.2 传统的程序设计概念程序由哪些基本成分构成?变量 · 数据类型 · 赋值 · 控制语句
6.3 过程单元函数如何实现模块化与复用?形参/实参 · 按值/按引用传递 · return
6.4 语言实现高级语言怎样变成机器可执行的形式?词法分析 · 语法分析 · 代码生成
6.5 面向对象程序设计如何用对象组织软件系统?类与对象 · 构造器 · 继承/多态/封装
*6.6 / *6.7 并发与说明性顺序之外还有哪些程序组织方式?并发活动 · 说明性程序设计
一条主线:要解决的问题 → 算法 → 程序设计语言 → 机器语言 → 计算机运行 → 问题得解。本章正是这条主线上承上启下的一环。
6.1 HISTORICAL PERSPECTIVE

6.1 历史回顾

程序设计语言的目标:让算法的表达既便于人理解,又便于转换为机器语言指令。

语言的三代演变:从 0/1 到接近人类语言

Generation 1 · Machine Language
机器语言
数字编码的指令序列直接写程序——烦琐、易出错。例:0x4056 表示“把寄存器 5 的内容移到寄存器 6”。
Generation 2 · Assembly Language
汇编语言
助记符(mnemonic)代替数字:mov R5, R6。由汇编器(assembler)转换为机器语言;但程序依赖特定机器,难以移植。
Generation 3 · High-Level Language
高级语言
原语更高级且机器无关assign TotalCost the value Price + ShippingCharge。由翻译器(translator)转换为机器语言。
解释器 vs 编译器:解释器(interpreter)在翻译出指令的同时执行指令,不产生供将来使用的机器语言副本;编译器(compiler)先把整个程序翻译成机器语言(目标程序 object program),之后再执行。

动手试一试:同一操作的三种写法

点击下面的标签,看“把寄存器 5 与 6 的和存入寄存器 7”在三代语言中分别长什么样——体会抽象层次的跃升。

程序设计范型:组织程序的四种思路

范型 paradigm:构建程序的风格或方法论。许多现代语言是多范型的(如 Python 同时支持命令式、函数式、面向对象)。

Imperative / Procedural
命令式(过程)范型
开发一个命令序列,遵照它对数据进行操作以产生期望结果——先找到算法,再把它表示为命令序列。代表:C、Pascal。
Declarative
说明性范型
程序员描述“要解决的问题”,而不是“要遵循的算法”——应用预先设定的通用问题求解算法。代表:Prolog、SQL。
Functional
函数范型
程序由较小的预定义函数连接而成:一个函数的输出直接作为下一个函数的输入。代表:LISP、Scheme。
Object-Oriented
面向对象范型
软件系统看作对象的集合,每个对象执行与自己相关的动作并响应其他对象的请求,相互作用共同解题。代表:Java、C++。
同一问题两种风格:计算支票簿余额。函数式(LISP):(Find_diff (Find_sum Old_balance Credits) (Find_sum Debits))——结果立即传给下一个函数;命令式则用多条语句把中间结果存入变量再逐步计算。用语言写算法:清晰度和可读性是最重要的考虑因素。
本节小结 · 6.1

语言三代:机器语言(数字编码)→ 汇编语言(助记符 + 汇编器)→ 高级语言(机器无关,需翻译器/解释器)。

四大范型:命令式、说明性、函数式、面向对象;几乎所有语言都能表达任何算法,但清晰度与可读性不同。

Q1汇编语言用助记符表示指令,把助记符程序转换为机器语言的程序称为?
A编译器
B解释器
C汇编器
D链接器
答案 C。汇编器(assembler)把助记符形式的汇编语言转换为机器语言;编译器/解释器处理的是高级语言。
Q2下列哪种范型要求程序员“描述要解决的问题,而不是要遵循的算法”?
A命令式范型
B函数范型
C面向对象范型
D说明性范型
答案 D。说明性范型(declarative paradigm)只描述问题本身,由预先设定的通用求解算法找出解法,如 Prolog、SQL。
6.2 TRADITIONAL PROGRAMMING CONCEPTS

6.2 传统的程序设计概念

高级语言的抽象分层:简单(常量/字面量/变量)→ 中等复杂(语句/表达式/控制结构)→ 深奥(过程单元/模块/库)。

程序的三种语句

Declarative Statement
声明语句
定义程序后面要用的自定义术语。例:int WeightLimit; —— 声明名字 WeightLimit 指向一个存放二进制补码数值的存储区域。
Imperative Statement
命令语句
描述底层算法中的步骤。例:z = x + y; —— 请求把表达式 x + y 的值存入变量 z 标识的存储区域。
Comment
注释
用人性化的形式解释程序中难懂的特性,提高可读性。例:// 计算气缸的容积
Control Statement
控制语句
可以改变程序执行顺序的命令语句——if-else 选择、while/for 循环都属于控制语句。
Overloading
重载
同一个运算符的多种用法:如 “+” 既表示数值相加,也可表示字符串拼接(取决于操作数的类型)。
脚本语言(scripting language):命令式语言的子集,通常用来执行管理任务而不是开发复杂程序;对这种任务的表述称为“脚本”(script),语言因此得名。赋值语句(assignment statement)= 变量 + 赋值符号 + 表达式,语义是对表达式求值并把结果存入变量。

变量、数据类型与数据结构

变量(variable):与存储位置相关联的名字——位置里的值随程序执行而改变。数据类型(data type)= 编码方式 + 可执行的操作。

数据类型English编码方式 / 可执行的操作
整型integer整数,常以二进制补码记数法存储;算术运算与大小比较
浮点型(实型)float / real可含小数,以浮点记数法存储;操作与整型一致
布尔型Boolean值仅为真或假;用于 if (LimitExceeded) 之类的条件判断
Primitive Data Type
基本数据类型
作为原语直接包含在语言中的数据类型,如整数的 int、字符的 char。
Constant & Literal
常量与字面量
常量给不变的值分配描述性名字;字面量文本用引号划界——“Smith” 是文本,Smith 是变量。
Data Structure
数据结构
数据在概念上的形态或排列。例:数组 array——相同类型元素组成的块,用索引 index 标识所需元素。
Expression
表达式
由算术运算符和逻辑运算符组合的变量、字面量和常量值——求值后得到一个结果。
本节小结 · 6.2

程序语句分三类:声明语句(定义术语)、命令语句(描述算法步骤)、注释(解释给人看)。

变量 = 名字 + 存储位置;数据类型 = 编码方式 + 可执行的操作(整型/浮点型/布尔型);数据结构是数据的概念形态,数组用索引访问元素。

Q3语句 int WeightLimit = 100; 属于哪一类程序语句?
A命令语句
B注释
C声明语句
D控制语句
答案 C。声明语句定义程序后面要用的术语,附带赋初值不改变其“声明”的本质。
Q4数据类型(data type)指的是?
A数据的存储地址
B数据的编码方式以及可以在该数据上执行的操作
C数据的名字
D数据的输入方式
答案 B。数据类型 = 编码方式 + 可执行的操作,二者缺一不可:整型按补码编码、可做算术;布尔型只有真/假。
6.3 PROCEDURAL UNITS

6.3 过程单元

函数是命令式语言获得程序模块化表示的主要技术——完成一个任务的一组指令,可用作其他程序单元的抽象工具。

void ProjectPopulation (float GrowthRate) { int Year; // 局部变量 Population[0] = 100.0; for (Year = 0; Year <= 10; Year++) Population[Year+1] = Population[Year] + Population[Year] * GrowthRate; }
C 语言函数:按增长率预测未来 10 年人口。
Call / Invoke
调用
将控制权转移给函数的过程;发出请求的程序单元称为“调用单元”。函数执行完后,控制权返回原来的程序单元。
Abstraction
抽象工具
开发抽象 = 去除细节 + 归纳功能;从具体示例中提取共同特征,让函数可在别处按名复用。
Why Functions
为什么用函数
软件复用、提高清晰度与可读性;较小的函数可以独立测试——更容易发现隐藏的 bug,从而更确信整个系统正确。

参数:形参、实参与传递方式

参数(parameter):函数内部的通用项——形参像函数体上的“槽口”,调用时实参被塞入槽口,按位置一一对应。

Formal / Actual Parameter
形式参数与实际参数
形参(formal parameter)是函数内部使用的项;实参(actual parameter)是调用时赋给形参的精确含义:第一个实参对应第一个形参。
Return Value
有返回值的函数
源于数学中的函数:输入集到输出集的关系。函数头指定返回值类型,return 语句终止函数并把值送回调用处。
Pass by Value
按值传递
把实参数据的副本传给函数——函数只改副本,调用单元中的数据受保护,不会被错误修改。
Pass by Reference
按引用传递
告诉函数实参的地址,函数可直接存取、修改调用环境中的数据——更灵活,也更需谨慎。
float CylinderVolume (float Radius, float Height) { float Volume; Volume = 3.14*Radius*Radius*Height; return Volume; } cost = CostPerVolUnit * CylinderVolume(3.45, 12.7);
有返回值的函数:计算结果可存进变量或立即参与计算。
实参顺序不能乱:PrintCheck("John Doe", 150) 正确;而 PrintCheck(150, "John Doe") 会把 150 当收款人!实参与形参按位置对应,顺序错了语义就全错。

动手试一试:按值传递 vs 按引用传递

同一个函数 Modify(n)(把形参加 10),分别以两种方式传递变量 x = 5。点击“执行调用”,观察调用单元的 x 是否被改变。

观察两侧“调用单元中的 x”有何不同
PASS BY VALUE
按值传递:函数拿到的是副本
调用单元 x
5
形参 n(副本)
等待执行……
PASS BY REFERENCE
按引用传递:函数拿到的是地址
调用单元 x
5
形参 n(即 x 的地址)
等待执行……
本节小结 · 6.3

函数 = 完成一个任务的一组指令;调用 = 控制权转移,执行完返回。形参是函数内的通用“槽口”,实参在调用时按位置塞入。

按值传递改副本,按引用传递改原件;有返回值的函数用 return 送回计算结果。通用性来自参数,而非写死的对象。

Q5“按值传递”(pass by value)参数时,函数对参数的修改会怎样?
A直接修改调用单元中的数据
B只修改实参的副本,调用单元的数据不受影响
C导致编译错误
D同时修改副本和原件
答案 B。按值传递只给函数一个副本,调用单元的原件受保护——这正是上面演示中左侧发生的情况。
Q6有返回值的函数通常用什么语句终止函数并把计算结果送回调用处?
Abreak
Bprint
Cyield
Dreturn
答案 D。return 语句终止函数执行,并把指定的值送回发出调用的程序单元。
6.4 LANGUAGE IMPLEMENTATION

6.4 语言实现

翻译 translation:把程序从一种语言转换成另一种语言。源程序 source program →(翻译)→ 目标程序 object program。

翻译过程:从源程序到目标程序

1 · Lexical Analyzer
词法分析器
逐个符号读源程序,识别出标记 token(单个实体的字符串),并分类为数值、单词、算术运算符等;跳过所有注释。
2 · Parser
语法分析器
把标记组合成语句:标识程序的语法结构、辨认每个成分的作用——本质上是为源程序构建语法分析树
3 · Code Generator
代码生成器
构造机器语言指令来实现语法分析器识别出的语句;代码优化(code optimization)是它的重要任务。

动手试一试:跟踪 z = x + y; 的翻译之旅

点击“下一步”,看一条赋值语句如何依次经过词法分析、语法分析、代码生成,最终变成机器指令。

源程序
SOURCE
源程序
STEP 1
词法分析
STEP 2
语法分析
STEP 3
代码生成
翻译流水线:源程序经词法分析、语法分析、代码生成变成机器代码
三个活动并非严格顺序执行,而是交织在一起:词法分析器每识别出足够的标记,语法分析器就组合出一个完整语句,随即请代码生成器产出对应指令——流水线式地推进。

软件开发包:一体化的开发环境(IDE)

Editor
编辑器
随时编写程序;按所用语言定制:自动行缩进、关键字自动补全、语法高亮(用颜色突出关键字),使程序更易读。
Translator
翻译器
一键把程序转换成机器语言,与编辑器无缝衔接——写完即可翻译、运行。
Debugger
调试工具
跟踪故障程序的执行,发现哪里出了问题;与编辑器来回切换,修改—测试的循环非常顺畅。
翻译过程本身就是面向对象的例子:源程序、词法分析器、语法分析器、代码生成器、目标程序都可以看作对象——每个对象在完成自己任务的同时,通过来回发送“消息”(标记、分析树、指令请求)与其他对象交互。
本节小结 · 6.4

翻译三活动:词法分析(认标记)→ 语法分析(组语句、建语法分析树)→ 代码生成(产出机器指令并优化),三者交织进行。

IDE 把编辑器、翻译器、调试工具组合成一个包:面对需要修改和测试的程序,可以在编辑器与测试工具之间轻松来回切换。

Q7翻译过程的三个活动按正确顺序是?
A语法分析 → 词法分析 → 代码生成
B词法分析 → 语法分析 → 代码生成
C代码生成 → 词法分析 → 语法分析
D词法分析 → 代码生成 → 语法分析
答案 B。词法分析认标记 → 语法分析组语句 → 代码生成产指令;实际执行中三者交织,但逻辑顺序如此。
Q8词法分析器(lexical analyzer)的主要工作是?
A构造机器语言指令
B为源程序构建语法分析树
C识别源程序中的标记(token)并分类
D跟踪程序执行以发现故障
答案 C。词法分析器逐个符号读源程序,识别并分类标记,跳过注释;建树是语法分析器的事,产指令是代码生成器的事。
6.5 OBJECT-ORIENTED PROGRAMMING · *6.6 · *6.7

6.5 面向对象 · *6.6 并发 · *6.7 说明性

OOP:软件系统看作对象的集合——每个对象执行与自己相关的动作并响应其他对象的请求,相互作用共同解题。

Class & Object
类与对象
(class)是一组对象的模板,描述共同特征;对象是从类构造出来的实例(instance),一个类可创建许多对象。
Constructor
构造器
与类同名的特殊方法,在构建类的对象时自动执行——完成对象的初始化。
Inheritance & Polymorphism
继承与多态
继承(inheritance):一个类包含其他类的属性;多态(polymorphism):多个对象以不同方式响应相同的方法调用。
Encapsulation
封装
限制对对象内部属性的访问:被封装的特性是私有的(仅对象自己可访问),其余是公有的。
*6.6 Concurrency
并发活动
同时执行多个计算任务或程序流程(而非一个接一个顺序执行),以增强程序的效率和响应能力。
*6.7 Declarative Programming
说明性程序设计
描述“是什么”而非“怎么做”:开发者专注期望的结果。形式逻辑提供通用求解算法——命题 + 与/或/非。
本节小结 · 6.5(含 *6.6 / *6.7)

OOP 四支柱:类是模板、对象是实例;构造器自动初始化;继承复用特征,多态同调异应,封装隐藏内部。

*6.6 并发 = 同时执行多个任务;*6.7 说明性 = 描述目标而非步骤,形式逻辑是底层引擎。

Q9在面向对象程序设计中,“类”(class)与“对象”(object)的关系是?
A类是对象的实例
B类是一组对象的模板,对象是从类构造的实例
C二者完全相同
D对象是类的模板
答案 B。类是模板,对象是实例;一个类可以创建许多对象。A 恰好说反了。
Q10限制对对象内部属性的访问、使被封装的特性成为私有的,这种技术称为?
A继承
B多态
C封装
D重载
答案 C。封装(encapsulation)= 限制对内部属性的访问;私有特性只有对象自己能访问,其余特性是公有的。
ANSWER KEY

课堂练习参考答案(共 10 题)

先独立完成上面的练习,再来这里核对——错题对应的小节值得回看一遍。

小节题号答案一句话解析
6.1Q1C汇编器(assembler)把助记符形式的汇编语言转换为机器语言。
6.1Q2D说明性范型:描述“要解决什么问题”,通用求解算法负责“怎么解”。
6.2Q3C声明语句定义程序后面要用的术语,赋初值不改变其声明本质。
6.2Q4B数据类型 = 编码方式 + 可执行的操作,二者缺一不可。
6.3Q5B按值传递只给函数一个副本,原件受保护。
6.3Q6Dreturn 终止函数并把值送回调用处。
6.4Q7B词法分析认标记 → 语法分析组语句 → 代码生成产指令。
6.4Q8C词法分析器逐个符号读源程序,识别并分类标记,跳过注释。
6.5Q9B类是模板,对象是实例;A 说反了。
6.5Q10C封装 = 限制对内部属性的访问;私有特性只有对象自己能访问。
答案速记
6.1 历史回顾
C · D
6.2 传统概念
C · B
6.3 过程单元
B · D
6.4 语言实现
B · C
6.5 面向对象
B · C
CHAPTER 6 · SUMMARY

全章总结

从 0/1 到对象:语言层次的每一次跃升,都让“人想出的办法”更容易变成“机器能执行的程序”。

小节一句话总结关键术语
6.1 历史回顾机器语言 → 汇编语言 → 高级语言;四大范型组织程序mnemonic · compiler · paradigm
6.2 传统概念声明/命令/注释三类语句;变量、类型、数组、赋值variable · data type · array
6.3 过程单元函数实现模块化;形参/实参;按值与按引用传递function · parameter · return
6.4 语言实现词法分析 → 语法分析 → 代码生成;IDE 一体化开发token · parse tree · IDE
6.5 面向对象类是模板对象是实例;继承、多态、封装class · object · encapsulation
*6.6 / *6.7并发同时执行多任务;说明性描述“是什么”concurrency · declarative
下一章预告:第 7 章《软件工程》将讨论如何把一个大型软件系统当作工程来建造——需求分析、设计、实现、测试与维护。语言给了我们“写程序”的工具,软件工程教我们“造系统”的方法。
GLOSSARY

本章术语表(中英对照)

重点名词双语对照 + 一句话释义;建议结课时自查一遍。

机器语言machine language数字编码的指令序列
助记符mnemonic代替机器码的易记符号
汇编语言assembly language助记符系统,依赖机器
汇编器assembler汇编语言 → 机器语言
编译器compiler翻译整个程序后执行
解释器interpreter边翻译边执行
程序设计范型paradigm构建程序的风格/方法论
命令式范型imperative paradigm命令序列操作数据
说明性范型declarative paradigm描述问题而非算法
函数范型functional paradigm函数嵌套连接
面向对象范型object-oriented paradigm对象相互作用解题
变量variable名字关联的存储位置
数据类型data type编码方式 + 可执行操作
数组array同类型元素组成的块
索引index标识数组元素的整数值
常量constant不变值的描述性名字
赋值语句assignment statement把表达式的值存入变量
重载overloading同一运算符的多种用法
控制语句control statement改变程序执行顺序
函数function完成任务的指令组
形式参数formal parameter函数内部的通用项
按值传递pass by value传副本,保护原件
按引用传递pass by reference传地址,可改原件
词法分析器lexical analyzer识别标记 token
语法分析器parser构建语法分析树
class一组对象的模板
对象object从类构造出的实例
封装encapsulation限制对内部属性的访问