侧边栏壁纸
博主头像
木云舟

行动起来,活在当下

  • 累计撰写 5 篇文章
  • 累计创建 0 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

软件设计师 · 程序设计语言知识考点详解

覆盖软考官方教程《程序设计语言基础知识》章节全部考点。 本章是上午科目必考内容,重点集中在:语言处理程序、编译过程各阶段、文法分类、正规式与有限自动机、中间代码(后缀式)、传值与传引用。

第 1 部分 程序设计语言概述

1.1 语言分类

类别

说明

示例

机器语言

二进制指令,可直接执行,效率最高但难读难写

机器码

汇编语言

用助记符代替机器码,需汇编程序翻译

MOV、ADD

高级语言

接近自然语言,需编译或解释执行

C、Java、Python

  • 低级语言(机器/汇编)与机器相关;高级语言与机器无关、可移植性强

  • 高级语言需要翻译才能执行,翻译方式:编译 或 解释

1.2 高级语言分类

类型

特点

代表语言

面向过程

以过程/函数为中心

C、Pascal、Fortran

面向对象

以对象/类为中心,封装、继承、多态

Java、C++、C#

函数式

以函数为基本单位,无副作用,λ 演算

Lisp、Haskell、Scheme

逻辑式

基于一阶谓词逻辑,声明式

Prolog

脚本语言

解释执行、动态类型、粘合程序

Python、JavaScript、Perl、Shell

标记语言

描述数据/展示格式

HTML、XML、JSON(数据交换)

数据库语言

数据定义/操纵

SQL

1.3 程序设计语言基本成分

  • 数据成分:常量、变量、数据类型(整型、实型、字符型、布尔型、数组、指针等)

  • 运算成分:算术运算、关系运算、逻辑运算

  • 控制成分:顺序、选择(if/switch)、循环(for/while)

  • 传输成分:输入输出


第 2 部分 语言处理程序(必考)

2.1 三种处理程序

程序

作用

输入 → 输出

汇编程序

汇编语言 → 机器语言

汇编源程序 → 目标程序

解释程序

逐句翻译并立即执行

源程序 → 直接执行结果

编译程序

整体翻译后执行

源程序 → 目标程序(可多次执行)

2.2 编译与解释对比(高频)

对比项

编译

解释

执行方式

先整体翻译成目标代码再运行

边翻译边执行

执行速度

快(目标代码直接执行)

慢

跨平台

需重新编译

有解释器即可运行

错误发现

编译时发现语法错误

运行到错误行才报错

典型代表

C、C++、Java(字节码+JVM)

Python、JavaScript、BASIC

生成目标代码

生成

不生成

注意:Java 是先编译成字节码,再由 JVM 解释/即时编译执行,属于"编译+解释"结合。


第 3 部分 编译过程(核心必考)

3.1 编译的六个阶段

阶段

任务

关键技术/产物

① 词法分析

读入字符流,识别记号(token)

正规式、有限自动机(DFA/NFA)

② 语法分析

将记号序列按文法组织成语法树

上下文无关文法、递归下降、LR

③ 语义分析

类型检查、声明检查、语义审查

类型系统、符号表

④ 中间代码生成

生成与机器无关的中间表示

后缀式、四元式、三元式

⑤ 代码优化

改进中间代码/目标代码

常量合并、循环优化等

⑥ 目标代码生成

生成机器指令/汇编代码

寄存器分配、指令选择

  • 符号表管理:记录标识符的属性(类型、地址、作用域),贯穿各阶段

  • 出错处理:发现并报告错误(语法错误、语义错误),贯穿各阶段

  • 前端(与机器无关):词法、语法、语义、中间代码生成

  • 后端(与机器相关):代码优化、目标代码生成

3.2 词法分析(重点)

  • 输入:源程序字符流;输出:记号流

  • 记号(token)由三部分构成:模式 + 词素 + 属性值

  • 记号种类:关键字、标识符、常量、运算符、界符

  • 实现工具:正规式(描述单词结构)+ 有限自动机(识别)

    • NFA(不确定有限自动机):同一状态对同一输入可有多个后继或 ε 转移

    • DFA(确定有限自动机):每个状态对每个输入符号有唯一后继

    • NFA 可等价转换为 DFA(子集构造法),DFA 可最小化

3.2.1 正规式(正则表达式,必考)

  • 正规式:用运算符描述字符串集合(正规集)的式子,是词法分析描述单词结构的工具

  • 运算符优先级(从高到低):*(闭包)> ·(连接)> |(或),括号最高;连接符 · 常省略

  • 运算含义:

运算

含义

示例

r | s

匹配 r 或 s(并)

a|b = {a, b}

r·s(rs)

先 r 后 s(连接)

ab = {ab}

r*

0 个或多个 r(闭包)

a* = {ε, a, aa, aaa, …}

r+

1 个或多个 r

a+ = aa*

  • 等价关系:正规式 ↔ 正规文法(3 型)↔ 有限自动机(NFA/DFA)三者等价

  • 【例题 1】 正规式 a(a|b)* 表示的语言? → 以 a 开头的任意 a、b 串(含单独的 a)

  • 【例题 2】 正规式 (a|b)a(a|b) 表示? → 含有至少一个 a 的任意 a、b 串

  • 【例题 3】 表示"以 00 结尾的二进制串"的正规式是? → (0|1)*00

3.2.2 有限自动机(必考)

  • DFA(确定有限自动机)五元组:M = (S, Σ, δ, s₀, F)

    • S:有限状态集合;Σ:输入字母表;δ:状态转移函数 S×Σ→S(唯一后继)

    • s₀:唯一初态;F:终态集合(可多个)

  • NFA(不确定有限自动机):δ 的后继不唯一,或存在 ε 转移

  • DFA 是 NFA 的特例;NFA 可用子集构造法转换为等价的 DFA

  • 用状态转换图表示:结点=状态,有向边标输入字符,初态标 →,终态用双圈

  • 串被接受:从初态出发沿字符转移,读完串后落在终态则接受

  • 【例题】 某 DFA 识别"偶数个 0"的二进制串:状态 A(偶数个 0,初态且终态)、B(奇数个 0);转移:A 读 0→B、读 1→A;B 读 0→A、读 1→B。判断串 0101 是否被接受? → A→(0)→B→(1)→B→(0)→A→(1)→A,落在终态 A(含 2 个 0,偶数)→ 接受

3.3 语法分析(重点)

  • 任务:按文法判断记号串是否符合语法规则,构造语法树(分析树)

  • 依据文法:上下文无关文法(2 型文法)

  • 自顶向下分析:递归下降分析法、LL(1) 分析法(预测分析)

  • 自底向上分析:LR(0)、SLR(1)、LR(1)、LALR(1) 分析法(移进-归约)

  • 二义性:一个句子存在两棵不同的语法树,则该文法有二义性(需改写消除)

3.3.1 推导与规约(考点)

  • 推导:从开始符号出发,反复用产生式替换非终结符,直至得到句子

    • 最左推导:每次替换最左边的非终结符;最右推导(规范推导):每次替换最右边的非终结符

  • 规约:推导的逆过程,从句子逐步归约为开始符号

  • 例:文法 E → E+E | EE | a,求 aa 的最左/最右推导

    • 最左推导:E ⇒ EE ⇒ aE ⇒ a*a

    • 最右推导:E ⇒ EE ⇒ Ea ⇒ a*a

  • 短语、直接短语、句柄(相对某句型):

    • 短语:句型中能规约为某个非终结符的子串

    • 直接短语:经一步规约得到的短语

    • 句柄:最左直接短语(最右推导的逆——最左规约所规约的对象)

乔姆斯基文法分类(必考)

类型

名称

产生式形式

识别装置

用途

0 型

短语结构文法

α → β(α、β 任意串)

图灵机

自然语言、通用

1 型

上下文有关文法

αAβ → αγβ(γ 非空)

线性有界自动机

—

2 型

上下文无关文法

A → γ

下推自动机

语法分析

3 型

正规文法(正则文法)

A → aB 或 A → a

有限自动机

词法分析

  • 包含关系:0 型 ⊇ 1 型 ⊇ 2 型 ⊇ 3 型

  • 判断技巧:产生式左侧只有一个非终结符 → 2 型;左侧非终结符前后有上下文 → 1 型;形如 A→aB / A→a → 3 型

【例题】 判断下列产生式所属文法类型:

  1. S → aS | a → 右线性形式 → 3 型(正规文法)

  2. S → aSb | ε → 左侧单非终结符 S,可生成 aⁿbⁿ → 2 型(上下文无关)

  3. aSb → aCb(非终结符 S 前后有 a、b 上下文)→ 1 型(上下文有关)

  4. ab → ba(左侧非单个非终结符)→ 0 型(短语结构)

3.4 语义分析

  • 任务:进行静态语义检查(类型检查、变量声明检查、运算合法性)

  • 输出:带类型信息等属性标注的语法树

3.5 中间代码(必考计算)

中间代码是与机器无关的中间表示,常见形式:

形式

示例(表达式 a*(b+c))

后缀式(逆波兰式)

abc+*

四元式

(+, b, c, t1)、(*, a, t1, t2)

三元式

(+, b, c)、(*, a, (1))

树(语法树)

根为 *,左子树 a,右子树 +

3.5.1 中缀转后缀(栈算法 + 运算符优先级)

  • 运算符优先级(从高到低):括号 > 单目 > *、/ > +、- > 关系 > 逻辑

  • 栈算法:

    1. 操作数直接输出

    2. 遇运算符:栈空、栈顶为 ( 或该运算符优先级高于栈顶 → 入栈;否则弹出栈顶输出,继续比较

    3. 遇 ( 入栈;遇 ) 依次弹出栈顶输出,直到弹出 ( 为止(括号不输出)

    4. 扫描结束,弹出栈中剩余运算符

  • 后缀式求值:用栈,遇操作数入栈,遇运算符弹出两个操作数运算后压回

  • 【例题】 转换下列中缀表达式为后缀式:

    1. a + b * c → abc*+

    2. (a + b) * c → ab+c*

    3. a + b * c - d → abc*+d-

    4. a*(b+c)-d → abc+*d-

    5. a+b*(c-d)/e → abcd-*e/+

3.5.2 四元式与三元式(例题)

  • 四元式:(运算符, 操作数1, 操作数2, 结果变量),用临时变量存中间结果

  • 三元式:(运算符, 操作数1, 操作数2),用位置编号引用中间结果

  • 例:a*(b+c)

    • 四元式:① (+, b, c, t1) ② (*, a, t1, t2)

    • 三元式:① (+, b, c) ② (*, a, (1))

  • 区别:四元式便于优化(可移动、重排);三元式省去临时变量、代码短,但移动/删除困难


第 4 部分 程序语言基础成分

4.1 数据类型

  • 基本类型:整型、实型(浮点)、字符型、布尔型

  • 构造类型:数组、结构体/记录、联合、枚举、指针、字符串

  • 抽象数据类型 ADT:数据 + 操作封装

4.1.1 数组存储与地址计算(了解)

  • 数组在内存中连续存储:行优先(C、C++)或列优先(Fortran)

  • 行优先:Loc(ai) = 起始地址 + (i × 列数 + j) × 元素大小

  • 列优先:Loc(ai) = 起始地址 + (j × 行数 + i) × 元素大小

  • 【例题】 二维数组 a3(3 行 4 列)按行优先存储,起始地址 100,每元素占 2 字节,求 a2 的地址? → Loc = 100 + (2×4 + 1)×2 = 100 + 18 = 118

4.2 变量与作用域

  • 静态作用域(词法作用域):作用域由程序文本结构决定(C、Java、Python 等绝大多数语言)

  • 动态作用域:作用域由调用关系决定(早期 Lisp)

  • 全局变量 / 局部变量;块结构

  • C 语言存储类别:auto(自动)、static(静态)、extern(外部)、register(寄存器)

4.2.1 作用域例题

int x = 1;
void f() { printf("%d", x); }
void g() { int x = 2; f(); }   // 调用 g 时
  • 静态作用域:f 中的 x 由文本结构决定,取全局 x → 输出 1

  • 动态作用域:f 运行时按调用链取最近的 x(g 的局部 x)→ 输出 2

4.3 参数传递(必考)

方式

行为

效果

传值(值传递)

把实参的值复制给形参

形参修改不影响实参

传地址/传引用

传递实参地址,形参是实参的别名

形参修改影响实参

传结果/传值结果

返回时把形参值写回实参

调用结束才影响

  • C 语言默认传值,用指针可实现传地址效果

  • Java 基本类型传值,对象传引用值

  • 例题:void swap(int a, int b) 交换 a、b 后,main 中实参不变 → 说明是值传递

4.3.1 参数传递经典例题

  • 【例题 1 传值】 C 语言 void swap(int a,int b){int t=a;a=b;b=t;} 调用 swap(x,y) 后 x、y 不变 → 值传递,形参是副本。

  • 【例题 2 传地址】 改用 void swap(int *a,int *b) 并调用 swap(&x,&y) → 通过指针改实参,x、y 交换成功。

  • 【例题 3 传引用】 C++ 中 void f(int &a,int &b) 传引用,形参是实参别名,调用后实参被修改。

  • 【例题 4 传值结果】 函数体内形参改变在返回时才写回实参,中途多次赋值以最后值为准。

4.4 函数与递归

  • 函数:参数 + 返回值,实现模块化

  • 递归:函数直接或间接调用自身,必须有递归出口(边界条件)

  • 递归 vs 迭代:递归代码简洁但开销大(栈),可用栈将递归转非递归

4.5 控制结构

  • 顺序结构、选择结构(if-else、switch)、循环结构(for、while、do-while)

  • 结构化程序设计:三种基本结构即可描述任意算法

4.6 运行时存储组织(了解)

  • 静态存储分配:编译时确定存储空间,用于全局变量、静态变量,运行期间不变

  • 栈式存储分配:运行时动态分配,用于函数调用的参数、局部变量、返回地址,后进先出

  • 堆式存储分配:运行时动态分配,大小/生命周期不定(malloc/new),需手动释放或 GC 回收

  • 活动记录(栈帧):函数调用时压入栈的一段存储,含参数、局部变量、返回地址、控制链


第 5 部分 典型程序设计语言特点(常考选择)

5.1 C 语言

  • 面向过程的高级语言,兼具低级语言能力(指针、位运算)

  • 指针是核心特色;无垃圾回收;内存需手动管理

  • 编译执行,效率高,广泛用于系统软件、嵌入式

5.2 C++ / Java / C#

语言

特点

C++

C 的超集,面向对象 + 过程;支持多继承、运算符重载、模板、多重继承

Java

纯面向对象;编译为字节码由 JVM 运行,跨平台;自动垃圾回收;单继承(接口实现多态);无指针

C#

微软 .NET 平台语言,面向对象,类 C++/Java

  • 面向对象三大特性:封装、继承、多态

  • 抽象类、接口、重载(编译时多态)、重写/覆盖(运行时多态)

  • 静态绑定(编译时绑定):重载、静态方法,编译期确定调用对象

  • 动态绑定(运行时绑定):重写/覆盖(虚函数、多态),运行期确定调用对象

5.3 脚本语言

  • Python:解释执行、动态类型、强制缩进、丰富的标准库

  • JavaScript:浏览器端脚本语言,原型继承、事件驱动

  • 特点:开发效率高、执行效率较低,常用于 Web、自动化

5.4 函数式语言

  • Lisp / Scheme / Haskell

  • 核心:函数是一等公民、无副作用(纯函数)、递归、λ 演算

  • 适合数学计算、AI 早期研究

5.5 逻辑式语言

  • Prolog:基于一阶谓词逻辑,由事实 + 规则 + 查询组成

  • 通过归结(消解)推理自动求解

5.6 标记与数据描述语言

  • HTML:网页展示结构

  • XML:可扩展标记语言,自定义标签,描述数据,跨系统交换

  • JSON:轻量级数据交换格式,键值对,易解析

5.7 数据库语言

  • SQL:数据定义(DDL)、数据操纵(DML)、数据控制(DCL)

  • 属于声明式语言(告诉"做什么"而非"怎么做")


第 6 部分 易混淆点与易错点

  1. 词法分析 ≠ 语法分析

    • 词法:识别单词(标识符、关键字、数字),用正规式 + 有限自动机

    • 语法:判断句子结构,用上下文无关文法 + 下推自动机

  2. 正规文法(3 型)对应有限自动机,用于词法;上下文无关文法(2 型)对应下推自动机,用于语法

  3. 编译 vs 解释:编译生成目标代码可重复执行;解释不生成目标代码,边译边执行

  4. 后缀式:运算符在操作数之后,用栈求值

  5. 传值 vs 传引用:传值不影响实参,传引用/传地址会影响实参

  6. 静态作用域 vs 动态作用域:静态由文本结构决定,动态由调用链决定

  7. Java 是单继承(C++ 支持多继承);Java 无指针、自动垃圾回收

  8. 1 型文法判断:产生式左右两侧出现上下文(αAβ → αγβ)

  9. 正规式 ↔ 正规文法 ↔ 有限自动机 三者等价

  10. 四元式 vs 三元式:四元式用临时变量存结果,三元式用位置编号引用结果

  11. 后缀式求值用栈;中缀转后缀运算符在操作数之后


第 7 部分 典型例题(真题风格)

  1. 后缀式:表达式 a - b * (c + d) 的后缀式为? → 先算括号:c d +;再乘:b c d + *;最后减:a b c d + * -

  2. 编译阶段:识别标识符、关键字属于哪个阶段? → 词法分析

  3. 文法类型:产生式 S → aS | ε 属于? → 形如 A→aA 或 A→a,属于 3 型(正规文法)

  4. 文法类型:产生式 A → aB | b 的识别装置是? → 有限自动机(DFA/NFA)

  5. 参数传递:C 语言中 void f(int x){ x=10; },调用后实参值? → 不变(值传递)

  6. 中间代码:四元式、三元式、后缀式都属于? → 中间代码(中间表示)

  7. 语言类型:Python 属于? → 脚本语言(解释执行、动态类型)

  8. 语言类型:Prolog 属于? → 逻辑式语言(一阶谓词逻辑、归结推理)

  9. 编译执行流程:源程序经过词法、语法、语义分析后生成? → 中间代码,再经优化生成目标代码

  10. 解释程序特点:不生成目标代码、执行速度慢、便于调试


第 7.5 部分 真题精练(含答案与解析)

以下为软考历年高频考查题型,建议先独立作答再核对答案。

  1. 【正规式】 正规式 a(b|a)* 表示的语言是( )。 → 以 a 开头的任意 a、b 串。

  2. 【正规式】 表示"由 a、b 组成且以 b 结尾"的字符串集合的正规式是( )。 → (a|b)*b。

  3. 【有限自动机】 某 DFA 识别"奇数个 0"的二进制串,则该 DFA 的终态是( )。 → 处于奇数个 0的那个状态。

  4. 【文法】 产生式 S → aS | ε 属于( )型文法。 → 3 型(正规文法),对应有限自动机,用于词法分析。

  5. 【文法】 文法 G:S → aSb | ε 生成的语言是( )。 → {aⁿbⁿ | n ≥ 0},属于 2 型(上下文无关文法)。

  6. 【编译阶段】 检查变量是否"先声明后使用"属于( )阶段。 → 语义分析(静态语义检查)。

  7. 【后缀式】 表达式 a + (b - c) * d 的后缀式是( )。 → abc-d*+。

  8. 【后缀式】 后缀式 ab+c* 对应的中缀表达式是( )。 → (a+b)*c。

  9. 【中间代码】 下列不属于中间代码形式的是( )。 A. 后缀式 B. 四元式 C. 三元式 D. 目标代码 → D。目标代码是编译最终产物,不是中间代码。

  10. 【参数传递】 C 语言函数参数默认的传递方式是( )。 → 值传递(形参修改不影响实参)。

  11. 【作用域】 采用动态作用域的语言,变量访问由( )决定。 → 运行时调用链(而非代码文本结构)。

  12. 【语言类型】 下列属于函数式语言的是( )。 A. C B. Java C. Lisp D. Prolog → C。Lisp 是函数式语言;Prolog 是逻辑式语言。

  13. 【编译vs解释】 下列语言中,通常采用解释方式执行的是( )。 A. C B. C++ C. Python D. 汇编 → C。Python 解释执行。

  14. 【C++/Java】 下列关于 Java 的说法正确的是( )。 A. 支持多继承 B. 有指针 C. 自动垃圾回收 D. 直接编译为机器码 → C。Java 单继承、无指针、自动 GC、编译为字节码由 JVM 运行。

  15. 【递归】 递归程序设计必须包含( )。 → 递归出口(边界条件),否则无限递归。


第 8 部分 复习策略建议

  1. 五大必考计算/判断:

    • 中缀 ↔ 后缀式转换(每年大概率 1 题)

    • 文法分类判断(0~3 型)

    • 编译各阶段功能归属

    • 正规式与有限自动机(等价关系、判定)

    • 参数传递方式(传值/传引用结果分析)

  2. 对比表重点背:编译/解释、词法/语法、NFA/DFA、传值/传引用、C/C++/Java

  3. 结合真题:近 5 年本章常考正规式、DFA、后缀式、文法类型、参数传递

  4. 编译原理部分偏理论,理解"输入→输出"的流水线关系即可,不必深究算法细节

  5. 程序语言特点题以常识记忆为主,注意区分脚本语言、函数式、逻辑式、标记语言


本笔记依据软考《软件设计师教程》程序设计语言基础知识章节整理,仅供备考复习使用。

0

评论区

书架