程序设计语言是为了书写计算机程序而人为设计的符号语言,用于对计算过程进行描述、组织和推导。
一、程序设计语言概述
1、基本概念
(1)低级语言和高级语言
- 计算机硬件只能识别由 0、1 组成的机器指令序列,即机器指令程序,因此
机器指令
是最基本的计算机语言。 - 用符号表示的指令称为汇编指令,汇编指令的集合被称为汇编语言。
人们称机器语言和汇编语言为低级语言。
面向各类应用的程序设计语言,称为高级语言。不依赖于机器硬件。
(2)编译程序和解释程序
计算机只能理解由 0、1序列构成的机器语言,因此高级程序设计语言需要翻译,担负这一任务的程序称为“语言处理程序”
。语言之间的翻译形式有多种,基本方式为汇编、解释和编译。
用某种高级语言或汇编语言
编写的程序称为源程序
,源程序不能直接在计算机上执行。
源程序是用汇编语言编写,需要汇编程序翻译(汇编)。
源程序是用高级语言编写,需要对应的解释程序或编译程序进行翻译(解释或编译)。
解释程序也叫解释器,直接解释执行源程序
,或将源程序翻译成某种中间代码再执行
。
编译程序也叫编译器,将源程序翻译成目标语言程序
,然后在计算机上运行目标程序
。
在解释方式下,翻译源程序时不生成独立的目标程序,而编译器则将源程序翻译成独立保存的目标程序。
(3)程序设计语言的定义
程序设计语言的定义都涉及语法、语义和语用等方面。
(4)程序设计语言的分类
程序设计语言有交流算法
和计算机实现
的双重目的。
命令式和结构化程序设计语言
命令式语言是基于动作的语言。
通常所称的结构化程序设计语言属于命令式语言类,其结构特性主要反映在以下几个方面:一是用自顶向下逐步精化的方法编程,二是按模块组织的方法编程,三是程序只包含顺序判定(分支)及循环构造,而且每种构造只允许单入口和单出口。
面向对象的程序设计语言
函数式程序设计语言
用函数和表达式建立程序的方法就是函数式程序设计
逻辑型程序设计语言
逻辑型语言是一类以形式逻辑为基础的语言,其代表是建立在关系理论和一阶谓词理论基础上的 PROLOG。
逻辑型程序设计具有与传统的命令式程序设计完全不同的风格。
(5)各种程序语言特点
- Fortran语言(科学计算,执行效率高)
- Pascal语言(为教学而开发的,表达能力强,Delphi )
- C语言(指针操作能力强,高效 )
- Lisp语言(函数式程序语言,符号处理,人工智能 )
- C++语言(面向对象,高效 )
- Java语言(面向对象,中间代码,跨平台)
- C#语言(面向对象,中间代码,.Net )
- Prolog语言(逻辑推理,简洁性,表达能力,数据库和专家系统 )
2、基本成分
程序设计语言的基本成分包括数据、运算、控制和传输等。
(1)程序设计语言的数据成分
程序设计语言的数据成分指一种程序设计语言的数据类型。
数据表示则指明了程序中值的组织形式。
数据是程序操作的对象,具有存储类别、类型、名称、作用域和生存期等属性,在使用时要为它分配内存空间。
存储类别说明数据在内存中的位置和生存期;
类型说明数据占用内存的大小和存放形式;
作用域则说明可以使用数据的代码范围;
生存期说明数据占用内存的时间特点。
不同角度可将数据进行不同的划分:
- 常量和变量
- 全局量和局部量
- 数据类型:基本类型、用户定义类型、构造类型及其他类型
(2)程序设计语言的运算成分
程序设计语言的运算成分指明允许使用的运算符号及运算规则。
基本运算可以分成算术运算、关系运算、逻辑运算、位运算。
(3)程序设计语言的控制成分
控制成分指明语言允许表述的控制结构,程序员使用控制成分来构造程序中的控制逻辑。程序可以用顺序、选择和循环这 3 种控制结构。
(4)程序设计语言的传输成分
程序设计语言的传输成分指明语言允许的数据传输方式,如赋值处理、数据的输入和输出等。
(5)函数
函数是程序模块的主要成分,它是一段具有独立功能的程序函数的使用涉及 3 个概念: 函数定义、函数声明和函数调用。
函数定义
函数的定义包括两部分: 函数首部和函数体。
函数声明
函数应该先声明后引用。
如果程序中对一个函数的调用在该函数的定义之前进行,则应该在调用前对被调用函数进行声明。函数原型用于声明函数。函数声明的一般形式为:返回值类型 函数名(参数类型表)
;
函数调用
当在一个函数(称为调用函数)中需要使用另一个函数(称为被调用函数)实现的功能时,便以名字进行调用,称为函数调用。
函数调用时,实参与形参间交换信息的方法有值调用
和引用调用
两种。
二、语言处理程序基础
语言处理程序是一类系统软件的总称,分为汇编程序、编译程序和解释程序。
1、汇编程序基本原理
(1)汇编语言
汇编语言是为特定的计算机设计的面向机器的符号化的程序设计语言。
用汇编语言编写的程序称为汇编语言源程序。
汇编语言源程序由若干条语句组成,其中可以有三类语句:指令语句、伪指令语句和宏指令语句。
指令语句
指令语句又称机器指令语句,将其汇编后产生相应的机器代码。基本的指令有ADD、SUB和AND等。
指令语句可分为传送指令、算术运算指令、逻辑运算指令、移位指令、转移指令和处理机控制指令等类型。
伪指令语句
伪指令语句:汇编程序在汇编源程序时完成某些工作,例如为变量分配存储单元地址,给某个符号赋一个值等。
伪指令语句与指令语句的区别:
- 伪指令语句经汇编后不产生机器代码,而指令语句经汇编后要产生相应的机器代码
- 伪指令语句所指示的操作是在源程序被汇编时完成的,而指令语句的操作必须在程序运行时完成。
宏指令语句
在汇编语言中,还允许用户将多次重复使用的程序段定义为宏。宏的定义必须按照相应的规定进行,每个宏都有相应的宏名。在程序的任意位置,若需要使用这段程序,只要在相应的位置使用宏名,即相当于使用了这段程序。因此,宏指令语句就是宏的引用。
(2)汇编程序
汇编程序的功能是将用汇编语言编写的源程序翻译成机器指令程序。
汇编程序一般需要两次扫描源程序才能完成翻译过程。
2、编译程序基本原理
(1)编译过程概述
编译程序的功能是把某高级语言书写的源程序翻译成与之等价的目标程序(汇编语言或机器语言)。
词法分析
词法分析阶段的任务是对源程序从前到后 (从左到右) 逐个字符地扫描,从中识别出一个个“单词”符号。“单词”符号是程序设计语言的基本语法单位,如关键字(或称保留字)、标识符、常数、运算符和分隔符 (如标点符号、左右括号) 等。
词法分析过程依据的是语言的词法规则,即描述“单词”结构的规则。
语法分析
语法分析的任务是在词法分析的基础上,根据语言的语法规则将单词符号序列分解成各类语法单位,如“表达式”“语句”和“程序”等。
语法规则就是各类语法单位的构成规则。
词法分析和语法分析在本质上都是对源程序的结构进行分析。
语义分析
语义分析阶段分析各语法结构的含义,检查源程序是否包含静态语义错误,并收集类型信息供后面的代码生成阶段使用。只有语法和语义都正确的源程序才能翻译成正确的目标代码。
语义分析的一个主要工作是进行类型分析和检查。
中间代码生成
中间代码生成阶段的工作是根据语义分析的输出生成中间代码。
出错处理
错误大致可分为静态错误和动态错误。
动态错误也称动态语义错误。
静态错误是指编译阶段发现的程序错误,可分为语法错误和静态语义错误。
(2)文法和语言的形式描述
字母表、字符串、字符串集合及运算
文法和语言的形式描述
(3)词法分析
词法分析的任务是把构成源程序的字符串转换成单词符号序列。
有限自动机
有限自动机是一种识别装置的抽象概念,它能准确地识别正规集。有限自动机分为两类:确定的有限自动机(DFA)和不确定的有限自动机(NFA)。
M
=
(
S
,
Σ
,
f
,
S
0
,
Z
)
M =(S, \Sigma,f,S_0,Z)
M=(S,Σ,f,S0,Z)
1)S是一个有限集,每个元素为一个状态
2)
Σ
\Sigma
Σ是一个有穷字母表,每个元素为一个输入字符
3)
f
f
f是转换函数:是一个单值对照。
f
(
A
,
a
)
=
Q
f (A,a)= Q
f(A,a)=Q表示当前状态为 A、输入为 a 时,将转换到下一状态 Q,称 Q为A 的一个后继状态
4)
S
0
S_0
S0属于S,是其唯一的初态
5)Z是一个终态集
不确定的有限自动机:对于 S 中的一个给定状态及输入符号,返回一个状态的集合即当前状态的后继状态不一定是唯一的。有向弧上的标记可以是
ϵ
\epsilon
ϵ 。
(4)正规式与有限自动机之间的转换
(5)词法分析器的构造
(6)语法分析
(7)语法制导翻译和中间代码生成
(8)中间代码优化和目标代码生成
3、解释程序基本原理
解释程序是另一种语言处理程序,在运行用户程序时,它直接执行源程序或源程序的中间表示形式
。因此,解释程序不产生源程序的目标程序,这是它和编译程序的主要区别。
解释程序实现高级语言的3种方式:
- 源程序被直接解释执行的处理方式如标记A 所示。这种解释程序对源程序进行逐个字符的检查,然后执行程序语句规定的动作。通过反复扫描源程序来实现程序的运行,运行效率很低。
- 解释程序先将源程序翻译成某种中间代码形式,然后对中间代码进行解释来实现用户程序的运行,这种翻译方式如标记 B 和 C 所示。不同于中间代码的级别。在方式 C 下,解释程序采用的中间代码更接近于机器语言
(1)解释程序的基本结构
解释程序通常可以分成两部分:
- 第一部分是分析部分,包括通常的词法分析、语法分析和语义分析程序,经语义分析后把源程序翻译成中间代码。
- 第部分是解释部分,用来对第一部分产生的中间代码进行解释执行。
(2)高级语言编译与解释方式的比较
对于高级语言的编译和解释工作方式,可以从以下几个方面进行比较。
- 效率:编译比解释可能获得更高的效率
- 灵活性:由于解释程序需要反复检查源程序,这也使得解释方式能够比编译方式更灵活。
- 可移植性:解释器一般也是用某种程序设计语言编写的,因此只要对解释器进行重新编译,就可以使解释器运行在不同的环境中。