7.用函数实现模块化程序设计

1.函数定义

指定函数的类型;指定函数的名字;指定函数的参数类型和名字;函数要完成的操作;

注:如果函数不需要返回值,则函数的类型应定义为void类型。

       如果函数有返回值,则函数返回值的类型必须和函数的类型一致。

 

2.定义空函数

void dummy(){},定义空函数是为将来需要扩充某些功能做准备。

 

3.函数参数

假设定义了一个int max(int a,int b)函数,则我们可以将此函数作为参数,如:

m=max(c,max(a,b));代表求出a,b,c三者中的最大值。

 

4.调用函数必须先声明

当我们调用一个函数的时候,必须要确保函数存在并且已经在main函数中进行了声明。

 

5.实际上,在函数声明中的形参名可以省略不写,而只写形参的类型。

如:float add(float,float);    编译系统只关心和检查参数个数和参数类型,而不检查参数名。

 

6.声明函数时,函数的首行(即函数首部)我们称为函数原型,函数原型一般的形式有两种:

1)函数类型 函数名(参数类型 参数名 ....)

2)函数类型 函数名(参数类型 ......)

 

7.函数定义与函数声明的区别

函数定义:指对函数功能的确立,包括函数名,函数类型,形参及其类型以及函数体等,它是一个完整,独立的函数单位。

函数声明:它的作用是把函数的名字,函数的类型以及形参的类型,个数和顺序通知给编译系统。

 

8.函数的递归调用

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。

一个递归问题可以分为回溯和递推两个阶段。



9.递归求n!的实例查看附件

 

10.汉诺塔(hanoi)问题。一个古典数学问题,问题是这样:古代有一个塔,塔内有3个座位A,B,C。开始时A上面有64个盘子,大的在下,小的在上。有一个老和尚想把64个盘子从A移到C,但每次只允许移动一个并且大盘在下,小盘在上。要求编程输出移到盘子的步骤。

注:详细解释在书中209页,代码见附件。

 

11.数组元素作为函数实参

数组元素可以用作函数实参,不能用作形参。因为形参是在函数被调用时临时分配存储单元的,不可能为一个数组元素单独分配存储单元(因为数组是一个整体,在内存中占连续的一段存储单元)。在用数组元素作函数实参时,把实参的值传给形参,是“值传递”方式。数据的传递方向是从实参传到形参,单向传递。

 

12.数组名作函数参数

除了用数组元素作为函数参数外,还可以用数组名作函数参数(包括实参和形参)。注意:用数组元素做实参时,向形参变量传递的是数组元素的值,而用数组名做函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址。

注:

1)用数组名作函数参数,应该在主调函数和被调用函数分别定义数组。

2)实参数组与形参数组类型应当一致,否则会出错。

3)实际上,指定数组长度的不是形参数组而是实参数组。因为C语言编译只是将实参数组的首元素的地址传给形参数组名。

4)形参数组可以不指定大小,在定义数组时在数组名后面跟一个空的方括号。

 

13.用数组名作函数实参时,不是把数组元素的值传递给形参,而是把实参数组的首元素的地址传递给形参数组,这样两个数组就共占同一段内存单元。

14.如果所调用的函数用的形参不是数组名参数,则会在编译的时候,为形参开辟一个临时的内存存储数据。

 

15.多维数组名作为函数参数

在调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小。

例如:int array[3][10] 或 int array[][10]

但是不能把第二维以及其他高维的大小省略。

 

16.全局变量

为了区别全局变量和局部变量,在C程序设计中,最好将全局变量名的第一个字母用大写表示。由于一个函数只能返回一个值,所以如果需要由一个函数得到多个值,我们就可能要考虑使用全局变量。

 

17.静态存储方式和动态存储方式

静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式;而动态存储方式则是程序运行期间根据需要进行动态的动态的分配存储空间的方式。

在内存中,供用户使用的存储空间的分为3个部分:(1)程序区(2)静态存储区(3)动态存储区。

数据分别存在静态存储区和动态存储区中:

全局变量存放在静态存储区,在程序开始时给全局变量分配存储区,程序执行完毕释放。在程序执行过程中它们占据固定的存储单元,而不是动态地进行分配和释放。

动态存储区中存放以下数据:

1)函数形式参数,在调用函数时给形参分配存储空间。

2)函数中定义的没有用关键字static声明的变量,即自动变量。

3)函数调用时的现场保护和返回地址等。

对于以上这些数据,在函数调用开始时分配动态存储空间,函数结束时释放这些空间。

 

18.在C语言中,每一个变量和函数都有2个属性:数据类型和数据的存储类别。对于数据类型,就是整型,浮点型等;刀对于存储类别,就是数据在内存中的存储方式(静态存储和动态存储)。

 

19.C语言的存储类别包括4种:自动的(auto),静态的(static),寄存器的(register),外部的(extern)。

 

自动变量(auto变量):函数中的局部变量,如果不专门声明为static(静态)存储类别,都是冬天地分配存储空间的,数据存储在动态存储区中。函数中的形参和在函数中定义的局部变量都属于此类。在调用函数时系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间,因此这类局部变量称为自动变量。

 

静态变量(static局部变量):有时希望函数中的局部变量的值在函数调用结束后不消失而继续保留原值,即其占用的存储单元不释放,在下一次再调用该函数时,该变量已有值(就是上一次函数调用结束时的值)。这时就应该指定该局部变量为静态局部变量。

 

寄存器变量(register变量):一般情况下,变量(包括静态存储方式和动态存储方式)的值都是存放在内存中的,当程序中用到哪一个变量的值时,由控制器发出指令将内存中的该变量的值运送到运算器中,经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。

 

由上可知:3种局部变量的存储位置是不同的,自动变量存储在动态存储区;静态局部变量存储在静态存储区;寄存器存储在CPU中的寄存器中。

 

外部变量:如果外部变量不在文件开头定义,其有效域的作用范围只限于定义处到文件结束。如果需要在定义点之前的函数需要引用该外部变量,则应该在引用之前用关键字extern,对该变量做外部变量声明。

 

20.将外部变量的作用域扩展到其他文件

如果程序由多个文件组成并且都要用到同一个外部变量Num,不能分辨在两个文件中定义Num,否则会出现重复定义错误。正确做法是:在任意一个文件中定义外部变量Num,然后在其他文件中用extern对Num做外部变量声明,即”extern Num“。

 

 21.将外部变量的作用域限制在本文件中

如果有时候只希望本文件用到此外部变量,其他文件不能用。就可以在定义此变量的时候加上static关键字,我们称为静态外部变量。

 

注:不要误认为对外部变量加static声明后,就采取静态存储方式,这是错误的。对于局部变量,只有加上了static才是以静态存储方式,而对于全局即外部变量来说,都是存放在静态存储区的。

 

 22.变量的定义和声明

在声明部分出现的变量有两种情况:一种是需要建立存储空间的(如:int a),另一种是不需要建立存储空间的(如extern a)。前者称为定义性声明或简称定义,后者称为引用性声明。

例如:int main()

{

    extern A ; //是声明,不是定义,声明将已经定义的外部变量A作用域扩展到此处

    ...... 

}

int A;    ​//是定义,定义A为整型外部变量

 

23.内部函数又称静态函数

如果一个函数只能被本文件中其他函数所调用,它称为内部函数,在定义内部函数时,在函数名和函数类型前面加 static 即:static 类型名 函数名(形参);

 

 24.外部函数

如果在定义函数时,在函数首部的最左端加关键字extern,则此函数是外部函数,可供其他文件调用。如函数首部可以为:extern int func(int a, int b);其中extern可以省略。

 

 

 

 

 

你可能感兴趣的:(谭浩强C程序设计第四版)