|
|
|
程序设计语言的基本成分包括数据、运算、控制和传输等。
|
|
|
|
|
|
程序中的数据对象总是对应着应用系统中某些有意义的东西,数据表示则指示了程序中值的组织形式。数据类型用于描述数据对象,还用于在基础机器中完成对值的布局,同时还可用于检查表达式中对运算的应用是否正确。
|
|
|
|
数据是程序操作的对象,具有类型、名称、作用域、存储类别和生存期等属性,在程序运行过程中要为它分配内存空间。数据名称由用户通过标识符命名,标识符常由字母、数字和称为下画线的特殊符号“_”组成;类型说明数据占用内存空间的大小和存放形式;作用域则说明可以使用数据的代码范围;存储类别说明数据在内存中的位置;生存期说明数据占用内存的时间范围。从不同角度可将数据进行不同的划分。
|
|
|
|
(1)常量和变量。按照程序运行时数据的值能否改变,将数据分为常量和变量。程序中的数据对象可以具有左值和(或)右值。左值指存储单元(或地址、容器),右值是值(或内容)。变量具有左值和右值,在程序运行的过程中其右值可以改变;常量只有右值,在程序运行的过程中其右值不能改变。
|
|
|
|
(2)全局变量和局部变量。按作用域可将变量分为全局变量和局部变量。一般情况下,系统为全局变量分配的存储空间在程序运行的过程中一般是不改变的,而为局部变量分配的存储单元是动态改变的。
|
|
|
|
(3)数据类型。按照数据组织形式的不同可将数据分为基本类型、用户定义类型、构造类型及其他类型。以C/C++为例,其数据类型如下。
|
|
|
|
.基本类型:整型(int)、字符型(char)、浮点型(float、double)和布尔类型(bool)。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
其中,布尔类型和类类型是C++在C语言的基础上扩充的。
|
|
|
|
|
|
程序设计语言的运算成分指明允许使用的运算符号及运算规则。大多数高级程序设计语言的基本运算可以分成算术运算、关系运算和逻辑运算等类型,有些语言如C(C++)还提供位运算。运算符号的使用与数据类型密切相关。为了明确运算结果,运算符号要规定优先级和结合性,必要时还要使用圆括号。
|
|
|
|
|
|
控制成分指明语言允许表述的控制结构,程序员使用控制成分来构造程序的控制逻辑。理论上已经证明,可计算问题的程序都可以用顺序、选择(分支)和循环这三种控制结构来描述。
|
|
|
|
(1)顺序结构。顺序结构用来表示一个计算操作序列。计算过程从所描述的第一个操作开始,按顺序依次执行后续的操作,直到序列的最后一个操作,如下图所示。
|
|
|
|
|
|
|
|
(2)选择结构。选择结构提供了在两种或多种分支中选择其中之一的逻辑。基本的选择结构是指定一个条件P,然后根据条件的成立与否决定控制流走分支A还是分支B,只能从两个分支中选择一个来执行,如下图(a)所示。选择结构中的A或B还可以包含顺序、选择和重复结构。程序设计语言中通常还提供简化了的选择结构,如下图(b)所示,还有描述多个分支的选择结构。
|
|
|
|
|
|
|
|
例如,C/C++提供了if、switch语句实现选择控制结构。
|
|
|
|
(3)循环结构。循环结构描述了重复计算的过程,通常由三个部分组成:初始化、需要重复计算的部分和重复的条件。其中,初始化部分有时在控制的逻辑结构中不进行显式的表示。重复结构主要有两种形式:while型重复结构和do-while型重复结构。while型结构的逻辑含义是先判断条件P,若成立,则进行需要重复的计算A,然后再去判断重复条件;否则,控制就退出重复结构,如下图(a)所示。do-while(或repeat-until)型结构的逻辑含义是先执行循环体A,然后再判断条件P,若成立则继续执行循环体A的过程并判断条件;否则,控制就退出重复结构,如下图(b)所示。
|
|
|
|
|
|
|
|
例如,C/C++提供了while、for和do-while语句来实现循环控制结构。
|
|
|
|
此外,C语言中还提供了实现控制流跳转的return、break、continue、goto语句。
|
|
|
|
程序设计语言的传输成分指明语言允许的数据传输方式,如赋值、数据的输入和输出等。
|
|
|
|
|
|
函数是程序模块的主要成分,它是一段具有独立功能的程序。C程序由一个或多个函数组成,每个函数都有一个名字,其中有且仅有一个名字为main的函数,作为程序运行时的起点。函数的使用涉及三个概念:函数定义、函数声明和函数调用。
|
|
|
|
|
|
函数的定义描述了函数做什么和怎么做,包括两部分:函数首部和函数体。函数定义的一般格式是:
|
|
|
|
|
|
函数首部说明了函数返回值的数据类型、函数的名字和函数运行时所需的参数及类型。函数所实现的功能在函数体部分描述。如果函数没有返回值,则函数返回值的类型声明为void。函数名是一个标识符,函数名应具有一定的意义(反映函数的功能)。形式参数表列举了函数要求调用者提供的参数的个数、类型和顺序,是函数实现功能时所必需的。若形式参数表为空,可用void说明。
|
|
|
|
C程序中所有函数的定义都是独立的。在一个函数的定义中不允许定义另外一个函数,也就是不允许函数的嵌套定义。有些语言(如PASCAL)允许在函数内部定义函数。
|
|
|
|
|
|
函数应该先声明后调用。如果程序中对一个函数的调用在该函数的定义之前进行,则应该在调用前对被调用函数进行声明。函数原型用于声明函数。函数声明的一般形式为:
|
|
|
|
|
|
使用函数原型的目的是告诉编译器传递给函数的参数个数、类型以及函数返回值的类型,参数表中仅需要依次列出函数定义时参数的类型。函数原型可以使编译器更彻底地检查源程序中对函数的调用是否正确。
|
|
|
|
|
|
当在一个函数(称为调用函数)中需要使用另一个函数(称为被调用函数)实现的功能时,便以名字进行调用,称为函数调用。在使用一个函数时,只要知道如何调用即可,并不需要关心被调用函数的内部实现。因此,程序员需要知道被调函数的名字、返回值和需要向被调函数传递的参数(个数、类型、顺序)等信息。
|
|
|
|
|
|
|
|
在C程序的执行过程中,通过函数调用使得被调用函数得以执行。函数体中若调用自己,则称为递归调用。
|
|
|
|
C语言采用传值方式将实参传递给形参。调用函数和被调用函数之间交换信息的方法主要有两种:一种是由被调用函数把返回值返回给调用函数,另一种是通过参数带回信息。函数调用时,实参与形参间交换信息的主要有传值调用和引用调用两种方法。
|
|
|
|
(1)传值调用(Call by value)。若实现函数调用时实参向形参传递相应类型的值,则称为是传值调用。这种方式下形参不能向实参传递信息。
|
|
|
|
例如,下面给出函数swap定义,其功能是交换两个整型变量值。
|
|
|
|
|
|
|
|
因为是传值调用,swap函数运行后只能交换x和y的值,而实参a和b的值并没有交换。
|
|
|
|
在C语言中,要实现被调用函数对实参的修改,必须用指针作形参,调用时需要先对实参进行取地址运算,然后将实参的地址传递给指针形参。本质上仍属于传值调用。
|
|
|
|
下面给出函数swap的定义,其功能是交换两个整型变量值。
|
|
|
|
|
|
|
|
由于形参px、py分别得到了实参变量a、b的地址,所以px指向的对象*px即为a,py指向的对象*py就是b,因此在函数中交换*px和*py的值实际上就是交换实参a和b的值,从而实现了调用函数中两个整型变量值的交换。这种方式是通过数据的间接访问来完成运算要求的。
|
|
|
|
(2)引用调用。引用是C++中增加的数据类型,当形参为引用类型时,函数中对形参的访问和修改实际上就是针对相应实参所作的访问和改变。例如:
|
|
|
|
|
|
|
|
引用调用方式下调用swap(a,b)时,x、y就是a、b的别名,因此,函数调用完成后,交换了实参a和b的值。
|
|
|