第七章——程序设计语言基础知识
第七章——程序设计语言基础知识
7.1 基本概念
7.1.1 低级语言和高级语言
通常称机器语言和汇编语言为低级语言。机器语言是指用0、1字符串组成的机器指令序列,是最基本的计算机语言。汇编语言是指用符号表示指令的语言。
高级语言是从人类的逻辑思维角度出发、面向各类应用的程序语言,其抽象程度大大提高,需要编译成特定机器上的目标代码才能执行。这类语言与人们使用的自然语言比较接近,大大提高了程序设计的效率。
程序设计语言的定义一般都涉及语法、语义、语用和语境等方面。
- 语法:由程序设计语言的基本符号组成程序中的各个语法成分的一组规则,其中由基本字符构成的符号书写规则称为词法规则,由符号构成语法成分的规则称为语法规则。程序语言的语法可通过形式语言进行描述。
- 语义:程序语言中按语法规则构成的各个语法成分的含义,可分为静态语义和动态语义
- 语用:表示构成语言的各个记号和使用者的关系,涉及符号的来源、使用和影响。
- 语境:理解和实现程序设计语言的环境,包括编译环境和运行环境。
7.1.2 程序设计语言的分类
- 命令式程序设计语言
命令式程序设计语言是基于动作的语言,在这种语言中,计算被看作是动作的序列,命令式语言族开始于Fortran、Pascal和C语言,体现了命令式程序设计的关键思想。 - 面向对象的程序设计语言
面向对象的程序设计在很大程度上应归功于从模拟领域发展而来的Simula,Simula提出了对象和类的概念。C++、Java和Smalltalk是面向对象程序设计语言的代表。 - 函数式程序设计语言
函数式程序设计语言是一类以2-演算为基础的语言。该语言的代表是LISP,其中大量使用了递归。 - 逻辑型程序设计语言
逻辑型程序设计语言是一类以形式逻辑为基础的语言。该语言的代表是建立在关系理论和一阶谓词理论基础上的Prolog。
7.1.3 程序设计语言的基本成分
数据成分:
- 常量和变量
- 全局量和局部量
- 数据类型
基本类型:整型(int)、字符型(char)、实型(float、double)和布尔类型(bool)。
特殊类型:空类型(void)
用户定义类型:枚举类型(enum)
构造类型:数组、结构和联合
指针类型:type
抽象数据类型:类类型
运算成分:
算术运算加减乘除、逻辑运算或与非、关系运算
控制成分:
顺序结构、选择结构、循环结构
函数和函数的调用
7.2 编译与解释
汇编语言是为特定的计算机或计算机系统设计的面向机器的符号化的程序设计语言。用汇编语言编写的程序称为汇编语言源程序。汇编语言源程序由若干条语句组成。一个程序中可以有3类语句:指令语句、伪指令语句和宏指令语句。
编译程序的功能是把用高级语言书写的源程序翻译成与之等价的目标程序。编译过程划分成词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成六个阶段,实际的编译器可能会将其中的某些阶段结合在一起进行处理。
解释程序是一种语言处理程序,在词法、语法和语义分析方面与编译程序的工作原理基本相同,但在运行用户程序时,它直接执行源程序或源程序的内部形式(中间代码)。因此,解释程序并不产生目标程序,这是它和编译程序的主要区别。
-
词法分析阶段的任务是:对源程序从前到后(从左到右)逐个字符进行扫描,从中识别出一个个“单词”符号。“单词”符号是程序设计语言的基本语法单位,如关键字、标识符等。
-
语法分析阶段的任务是:在词法分析的基础上,根据语言的语法规则将单词符号序列分解成各类语法单位,如“表达式”“语句”和“程序”等。词法分析和语法分析本质上都是对源程序的结构进行分析。
-
语义分析阶段主要是:审查源程序是否存在语义错误,并收集类型信息供后面的代码生成阶段使用,只有语法和语义都正确的源程序才能翻译成正确的目标代码。语义分析的一个主要工作是进行类型分析和检查。
-
中间代码生成阶段的工作:是根据语义分析的输出生成中间代码。
-
代码优化阶段的任务是:对前一阶段产生的中间代码进行变换或进行改造,目的是使生成的目标代码更为高效,即省时间和省空间。
-
目标代码生成阶段的任务是:把中间代码变换成特定机器上的绝对指令代码、可重定位的指令代码或汇编指令代码。这是编译的最后阶段,它的工作与具体的机器密切相关
7.3 文法
一个形式文法是一个有序四元组G=(V,T,S,P),其中
- V:非终结符。不是语言组成部分,不是最终结果,可理解为占位符
- T:终结符。是语言的组成部分,是最终结果。V⋂T=Ø
- S:起始符。是语言的开始符号。
- P:产生式。用终结符替代非终结符的规则。形如α->β
7.3 语法推导树
一棵语法树应具有以下特征:
- 每个结点都有一个标记,此标记是V的一个符号
- 根的标记是S
- 若一结点n至少有一个它自己除外的子孙,并且有标记A,则A肯定在VN中;
- 如果结点n的直接子孙,从左到右的次序是结点n1,n2..nk,其标记分别是:A1,A2,…,Ak,那么A>A1,A2…Ak,一定是P中的一个产生式。
7.4 有限自动机
先分清初态和终态
7.5 正规式
有限自动机的另一种表达形式
7.6 表达式
传值与引用(传址)
传值调用:形参取的是实参的值,形参的改变不会导致实参的值发生改变
引用(传址)调用:形参取的是实参的地址,即相当于实参存储单元地址的引用,因此其值改变的同时就改变了实参的值
在您提供的描述中,有几个问题需要澄清和修正,因为C语言不支持直接在函数调用中使用引用(&在C语言中通常表示取地址操作符,而不是引用)。不过,我可以假设您想要表达的是使用指针来达到类似引用的效果。
首先,我将提供一个假设的C语言程序,它可能符合您想要的功能:
#include <stdio.h>
void f(int x, int *a) {
x = 2 * x - 1;
*a = *a + x;
}
void print(int x) {
printf("%d\n", x);
}
int main() {
int x = 10;
f(x, &x); // 传递x的值和地址给f
print(x); // 打印修改后的x
return 0;
}
现在,我们分析这个程序:
在main函数中,我们定义了一个整数x并初始化为10。
我们调用f(x, &x),将x的值和地址作为参数传递给f函数。
在f函数中,我们首先计算x = 2 * x - 1(这里的x是函数内部的局部变量,它不会影响main中的x)。然后,我们将这个计算结果加到通过指针a指向的整数上(这个整数实际上是main中的x)。
f函数返回后,main中的x已经被修改为x + (2*x - 1),即x + 2x - 1 = 3x - 1。
最后,我们调用print(x)打印修改后的x的值。
对于初始值x = 10,最终的x的值将是3 * 10 - 1 = 29。所以程序运行的结果是打印出数字29。
但是,如果您真的想要在C语言中使用引用(就像C++中那样),那么您需要使用指针,或者考虑使用C++来编写您的程序。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!