1.程序设计语言
低级语言:机器语言和汇编语言。
- 机器语言:二进制代码,语句为0和1运行快但可读性差,难理解和维护。
- 汇编语言:用符号(ADD、SUB)表示的指令,运行快可移植性差。
- 高级语言:面向各类的程序语言,如Java、C、C++、C#、Python、PHP、JavaScript。
高级语言或汇编语言编写的程序称为源程序,源程序不能直接在计算机上执行,必须进行翻译,基本翻译方式为汇编、解释和编译。
如果源程序是用汇编语言编写的,则需要一个汇编程序将其翻译成目标程序后才能执行。如果源程序是用某种高级语言编写的,则需要对应的解释程序或编译程序对其进行翻译,然后在机器上运行。
解释程序也称为解释器,它或者直接解释执行源程序,或者将源程序翻译成某种中间代码后再加以执行;编译程序 (编译器)则是将源程序翻译成目标语言程序,然后在计算机上运行目标程序。
编译程序和解释程序的主要区别:
- 在编译方式下,机器上运行的是与源程序等价的目标程序,源程序和编译程序都不再参与目标程序的执行过程。
- 在解释方式下,解释程序和源程序(或其某种等价表示)要参与到程序的运行过程中,运行程序的控制权在解释程序。
简单来说,在解释方式下,翻译源程序时不生成独立的目标程序,而编译器则将源程序翻译成独立保存的目标程序。
汇编程序用在汇编语言,通常有以下指令语句需要注意:
- 指令语句:通过汇编程序生成中间代码,能在cpu中执行。
- 伪指令语句:不能通过汇编程序,汇编成机器代码,在汇编阶段定义。
- 宏指令语句:一段代码指令反复执行。
2. 程序设计语言的特点和分类
各种程序语言主要特点:
- Fortran 语言。科学计算,执行效率高。
- Pascal 语言。为教学而开发的,表达能力强,Delphi 可视化工具。
- C 语言。指针操作能力强,高效。
- Lisp 语言。函数式程序语言,符号处理,人工智能。
- C++ 语言。面向对象,高效。
- Java 语言。面向对象,中间代码,跨平台。
- C# 语言。面向对象,中间代码,.NET Framework 微软开发。
- Ruby 语言。面向对象,动态类型的脚本语言。
- PHP 语言。可以快速地执行动态网页,混合了C、Java、Perl等语法。
- JavaScript 语言。广泛应用于Web,常用来为网页添加各式各样的动态功能。
- Perl 语言。对文本处理高效。
- Prolog 语言。逻辑推理,简洁性,表达能力强,数据库和专家系统。
- HTML 语言。超文本标记语言,设计网页。
- Python 语言。面向对象的解释型程序设计语言,可以用于编写独立程序、快速脚本和复杂应用的原型。
程序设计语言的分类:
- 命令式程序设计语言。命令式语言是基于动作的语言,在这种语言中,计算被看成是动作的序列。常见的语言有 Fortran、Pascal、C、Python。
- 面向对象的程序设计语言。常见的语言有 C++、Java、C#。
- 函数式程序设计语言。函数是一种对应规则 (映射),它使定义域中每个元素和值域中唯一的元素相对应。常见的语言有 Lisp。
- 逻辑型程序设计语言。逻辑型语言是一类以形式逻辑为基础的语言,其代表是建立在关系理论和一阶谓词理论基础上的 Prolog。
3. 编译程序(编译器)的工作原理
程序设计语言的定义涉及语句、语法、语义和语用:
- 语句是可执行的语句,有简单语句和复合语句。
语法是指由程序语言的基本符号组成程序中的各个语言结构(包括程序)的一组规则。其中由基本字符构成的符号(单词)书写规则称为词法规则;由符号构成语法成分的规则称为语法规则。
语义是程序语言中按语法规则构成的各个语法成分的含义,可分为静态语义和动态语义。静态语义指编译时可以确定的语法成分的含义,而运行时才能确定的含义是动态语义。
语用表示构成语言的各个记号和使用者的关系,涉及符号的来源、使用和影响。语言的实现则有个语境问题。语境是指理解和实现程序设计语言的环境,包括编译环境和运行环境。
编译程序的作用是把某高级语言书写的源程序翻译成与之等价的目标程序(汇编语言或机器语言形式)。编译程序的工作一般可以分为6个阶段,如下:
- 词法分析。对源程序从前到后(从左到右)逐个字符地扫描,识别出一个个单词。
- 语法分析。在词法基础上,根据语言的语法规则将单词符号序列分解成各类语法单元,如表达式、语句和程序等。
- 语义分析。分析语法结构的含义,检查源程序是否包含静态语义错误,并收集类型信息供后面的代码生成阶段使用。只有语法和语义都正确的源程序才能翻译成正确的目标代码。主要工作是进行类型分析和检查。
- 中间代码生成。根据语义分析的输出生成中间代码,最常用的4种中间代码是与汇编语言的指令非常相似的
三地址码
,其实现方式常采用四元式
。 - 代码优化。生成的中间代码往往在时间和空间方面的效率较差,
优化过程可以在中间代码生成阶段进行,也可以在目标代码生成阶段进行。
- 目标代码生成。把中间代码变换成特定机器上的绝对指令代码、可重定位的指令代码或汇编指令代码,这个阶段的工作与具体的
机器
密切相关。 - 符号表管理。符号表的作用是记录源程序中各符号的必要信息,以辅助语义的正确性检查和代码生成,在编译过程中需要对符号表进行快速有效地查找、插入、修改和删除等操作。
符号表的建立可以始于词法分析阶段,也可以放到语法分析和语义分析阶段,但符号表的使用有时会延续到目标代码的运行阶段。
出错处理。大致可分为静态错误和动态错误。
动态错误
也称动态语义错误,它们发生在程序运行时,例如变量取零时作除数、引用数组元素下标错误等。静态错误
是指编译阶段发现的程
- 序错误,可分为语法错误和静态语义错误,如单词拼写错误、标点符号错误、表达式中缺少操作数、括号不匹配等有关语言结构上的错误称为语法错误,而语义分析时发现的运算符与运算对象类型不合法等错误属于静态语义错误。
4. 程序语言的数据成分
程序语言的基本成分包括数据、运算、控制和传输。
4.1 数据成分
数据是程序操作的对象,具有以下属性:
- 数据名称:由用户通过标识符命名,标识符是由字母、数字和下画线
_
组成的标记。 - 数据类型:说明数据占用内存的大小和存放形式。
- 存储类别:说明数据在内存中的位置和生存期。
- 作用域:说明可以使用数据的代码范围。
- 生存期:说明数据占用内存的时间范围。
从不同角度可将数据进行不同的划分。
1)常量和变量
根据程序运行时数据的值能否改变,可以将程序中的数据分为常量和变量。程序中的数据对象可以具有左值和(或)右值,左值指存储单元(或地址、容器),右值是值(或内容)。
2)全局变量和局部变量
根据数据的作用域范围,可将其分为全局变量和局部变量。系统为全局变量分配的存储空间在程序运行的过程中一般是不改变的,而为局部变量分配的存储单元是可以动态改变的。
3)数据类型
根据数据组织形式的不同可将数据分为基本类型、用户定义类型、构造类型及其他类型。,以C/C++为例,数据类型如下:
基本类型:整型(int)、字符型(char)、实型(float、double)和布尔类型(bool)。
特殊类型:空类型(void)。
用户定义类型:枚举类型(enum)。
构造类型:数组、结构、联合。
指针类型:type *。
抽象数据类型:类类型。
其中,布尔类型和类类型由C++语言提供。数据类型转换规则:char,short->int->unsigned->long,float->double。强制转换和隐式转换。
4.2 运算成分
程序语言的运算成分指明允许使用的运算符号及运算规则。大多数高级程序语言的基本运算可以分成算术运算、关系运算和逻辑运算等,有些语言如C/C++还提供位运算。运算符号的使用与数据类型密切相关。为了明确运算结果,运算符号要规定优先级和结合性,必要时还要使用圆括号。
操作符放置位置,可以分为以下表达式:
前缀表达式:(+ a b)。
中缀表达式:(a + b)。
后缀表达式:(a b -),又称逆波兰式。
程序设计中,是通过栈来实现表达式。
表达式转换解题方法:
先构造二叉树,再后序遍历。
加括号,再移动运算符。
4.3 控制成分
- 顺序结构:是一种线性有序的结构,由一系列依次执行的语句或模块构成。
- 选择结构:根据条件成立与否,从两种或多种分支选择其中一个的逻辑。
- 循环结构:是由一个活几个模块构成,程序运行时重复执行,直到满足某一条件为止。
(a) while 型结构的逻辑含义是先判断条件P,若成立则执行循环体A,然后再去判断条件P;否则控制流就退出循环结构。
(b) do-while 型结构的逻辑含义是先执行循环体A,然后再判断条件P,若成立则继续执行A的过程并判断条件;否则控制流就退出循环结构。
两种区别是 do-while 型结构会比 while 型结构多一次执行。
4.4 传输成分
函数是程序模块的主要成分,它是一段具有独立功能的程序代码。
C 程序由一个或多个函数组成,每个函数都有一个名字,其中有且仅有一个名字为 main 的函数,作为程序运行时的起点。
函数的使用涉及三个概念:函数定义、函数声明和函数调用。
(1)函数定义
包括函数首部和函数体两部分。函数的定义描述了函数做什么和怎么做。函数定义的一般格式是:
int FunctionExample (int x,float y) 返回值的类型 函数名(形式参数表) //函数首部 { 函数体; }
函数首部说明了函数返回值的数据类型、函数的名字和函数运行时所需的参数及类型,其中参数为形参
。函数所实现的功能在函数体部分进行描述。
(2)函数声明
对于函数,应该先声明后引用。如果程序中对一个函数的调用在该函数的定义之前进行,则应该在调用前对被调用函数进行声明。函数原型用于声明函数。函数声明的一般形式为:
返回值类型 函数名(参数类型表);
使用函数原型的目的是告诉编译器传递给函数的参数个数、类型以及函数返回值的类型,参数表中仅需要依次列出函数定义时参数的类型,以使编译器能更彻底地检查源程序中对函数的调用是否合适。
(3)函数调用
当在一个函数(称为主调函数)中需要使用另一个函数(称为被调函数)实现的功能时,便以名字进行调用,称为函数调用。
函数调用的一般形式:
函数名(实参表)
调用函数和被调用函数之间交换信息的方法主要有两种:一种是由被调用函数把返回值返回给主调函数;另一种是通过参数带回信息。
函数调用时实参与形参间交换信息的方法有传值调用和传址调用:
- 传值调用:实际上重新复制了一个副本给形参,不改变调用函数实参变量的内容。这种方式下形参不能向实参传递信息。
- 传址调用:又称引用调用,将实参地址给形参,将改变调用函数实参变量的内容。