1、1 / 54,函 数,2 / 54,一、函数的定义 1、概 述 2、函数的定义 3、函数的参数 4、函数的返回值 二、函数的调用 1、函数的一般调用 2、函数的嵌套调用 3、函数的递归调用,教学要点,3 / 54,三、数组作为函数的参数 1、数组元素作为函数的实参 2、数组名作为函数的参数 3、二维数组作为函数的参数 四、局部变量与全局变量 五、变量和函数的存储类别 六、内部函数与外部函数,教学要点,1、含义:函数是完成一个独立功能的程序代码。 2、C程序的基本结构(如图): 3、例81: 4、要点:,概 述,例8_1:函数的结构,对函数的理解: 一个源程序由一个或多个函数组成。 一个C程序由
2、一个或多个源程序组成。 c程序的执行顺序从main()开始,调用其他函数后,流程回到main()函数。 c程序的所有的函数都是平行的,不存在函数的嵌套定义。 从用户的角度对函数的分类: (1)标准库函数:由系统提供。 (2)用户自定义函数:解决用户的专门需要。 从函数的形参对函数的分类: (1)无参数函数:用于执行指定的一组操作,可以带回或不带回函数值。 (2)有参数函数:主调函数可以将数据传给被调函数使用,被调函数中的数据也可以带回给主调函数使用。,7 / 54,函数的定义,1.无参数函数的定义 函数类型说明符 函数名() 如:printstar() 函数说明部分; printf(“*n”)
3、;语句块; 2.有参数函数的定义 函数类型说明符 函数名(形式参数表) 形参说明 如:int add(int x,int y) 函数说明部分; int z;语句块; return x+y; 3.例82: 4.要点:,例8_2:函数的定义,int max(int x,int y),9 / 54,1、函数的类型:即函数返回值的类型(缺省时为整型)。若不返回任何值,则应将其类型定义为void。 2、函数名的定义: 规则:按“见名知意” 表示法。 含义:函数名代表此函数在内存中的起始位置。 3、形参的定义: 形参的个数和类型均由函数的功能来决定。 4、空函数的定义: 函数体无任何语句。,函数定义要点,
4、10 / 54,函数的参数,1、形式参数 写在函数定义中函数名后面括号中的变量叫做“形式参数” 2、实际参数 出现在函数调用时,函数名后面括号中的表达式称为“实际参数”.例82: 3、要点: 形参变量只有在函数被调用时才占用内存空间,调用结束后所占空间即被释放; 在函数定义时必须指出形参的类型; 实参与形参的类型必须一致; 实参可以是常量,变量或表达式; 实参对形参的传递数据是单向传递(值传递);,1、函数的返回值是通过函数中的return语句来完成的,return语句一次只能返回一个值; 2、由return语句返回的数据类型应与函数定义时的类型一致。例83: 3、当在函数的定义时,未指出函数
5、的类型,c语言默认的类型为整型. 4、函数没有return语句并不表明函数没有返回值,只是这个返回值对于调用者来说可能是没有用的,这个返回值随函数的不同它的值也不尽相同. 5、如果我们明确表示函数不能返回值,在函数的定义时用“void”加以说明,这样可以确保函数不带回返回值. 6、例84:,函数的返回值,12 / 54,例8_3:函数返回值类型与函数类型不符,输出: max is 2,输入: 1.5,2.5,13 / 54,例8_4:对函数返回值的理解:,若不需要函数带回任何值,可使用:,14 / 54,函数的一般调用,1、函数调用的一般形式: 函数名(实参表列); 如:add(int x,i
6、nt y) 的调用为add(2,3) 2、函数调用的规则: 实参与形参在个数与类型上必须保持一致。 当函数无参数时,实参表列就为空,但括号不能少。 实参表列中的各个参数之间用逗号隔开。 实参与形参是一一对应的关系(函数调用的过程)。 对于实参表的求值顺序各个系统是不一致的。例85: 3、函数调用的方式 4、函数的引用性说明,15 / 54,例8_5:实参表求值顺序的一致,一般改为: j=i; k=+i; p=(j,k),输出: 0,或 j=+i;p=f(j,j),1.函数语句: 功能:将函数调用作为一个语句。 如:printf(“book”); 要点:不要求函数带回值,只要求完成一定的操作。
7、2.函数表达式: 功能:将函数作为表达式的一部分。 如: c=2*max(a,b); 要点:要求函数带回一个确定的值,以参加表达式的运算。 3.一个函数作为另一个函数的参数: 功能:将函数的调用作为一个函数的实参。 如: m=max(a,max(b,c)); 要点:其实质也是函数表达式的调用。,函数调用的方式,1.被调用函数必须是一个已经存在的函数. 2.如果使用库函数应在文件头加上#include命令,以便将有关的库函数包含到本源文件中来. 3.对于用户自定义函数,函数的定义部分应出现在该函数被调用之前.不然的话,在调用函数之前应作提前说明. 4.引用性说明的方法: 返回值类型 函数名( )
8、 如: int add(int,int, ); 5.例86:,函数的引用性说明,18 / 54,例8_6:函数的引用性说明:,输出:sum is 9.10000,输入:3.6,5.5,1、含义:所谓函数的嵌套调用是指一个函数在被调用时其本身又调用了其他函数. 2、嵌套调用的过程: main() a函数 b函数调用a函数 调用b函数结束 3、例87:,函数的嵌套调用,20 / 54,例8_7:函数的嵌套调用,swap(a,b); /调用,输出: 5,33,5,1、含义:在调用一个函数的过程中又直接或间接的调用函数自身叫做函数的递归调用. 2、直接递归调用:例88 3、间接递归调用:例89 4、要
9、点: 不论是直接调用还是间接调用,要使调用能够终止必须有一个使调用终止的条件,不然的话调用将陷入无终止状态. 5、例810、811、812,函数的递归调用,22 / 54,例8_8:函数的直接递归调用,int f(int x) int y,z;z=f(y);return (2*z); ,例8_9:函数的间接递归调用int f1(int x) int y,z;z=f2(y);return (2*z); ,int f2(int t) int a,c;c=f1(a);return (3+c); ,例8_10: 有五个人坐在一起,问第五个人有多少岁?他说比第四个人大两岁.问第四个人的岁数,他说比第三个
10、人大两岁,问第三个人的岁数,他说比第二个人大两岁,.当问到第一个人时,他说自己10岁,请问第五个人的岁数?age(5)=age(4)+2age(4)=age(3)+2age(3)=age(3)+2age(2)=age(1)+2age(1)=10,递归调用的过程,运行结果为: 1 age is 102 age is 123 age is 144 age is 165 age is 18,例8_11: 用递归的方法求n!,例8_12:求下面程序的输出结果。,运行结果为:7290,1、含义:数组元素作为表达式的组成部分,与变量作实参一样,都是按“值传递”进行单向传送. 2、例8_13:,数组元素作为
11、函数的实参,运行结果:1 2 3 4 5 6 7 8 9 10,1.数组名作为函数的参数,应在调用函数和被调用函数中分别定义数组. 2.形参与实参的类型应一致. 3.实参与形参的数组的大小可以一致也可以不一致,形参接收的是实参传来的数组的首地址,对数组的大小不作检查. 4.数组名作函数的参数传递时, 实参传递给形参的不是一个简单的数值,而是一段内存单元的首地址,在被调用函数中对这段地址所指向的单元的内容改变时,将反映到调用函数中. 5.例814、815:,数组名作为函数的参数,例8_14:数组名可作为函数的参数,这时形参和实参都是数组名(或指针).,运行结果:hgfedcba,例8_15:用选
12、择法对数组中的10个数进行排序. 选择法的解题思路: (1)将10个数中的所有数逐个进行比较找出其中的最小数,将这个最小数与a0进行交换; (2)将剩下的9个数中的所有数逐个进行比较找出其中的最小数,将这个最小数与a1进行交换; (3)以此类推.,int array,n;,1、用法:多维数组名也可以作函数的参数,从调用函数到被调用函数依然传递的是地址,形参中的数组定义可以省略第一维的大小说明,但第二维的说明不可少. 2、例8_16: 有一个3*4的矩阵,求出其中的最大元素的值.,二维数组作函数的参数,1、含义:在一个函数内部定义的变量,其作用范围为函数体内部。 2、作用范围 3、使用要点: (
13、1)主函数中定义的变量也只在主函数中有效; (2)不同的函数中可以使用相同的变量名,它们代表不同的含义; (3)形参也是局部变量; (4)在一个函数内部可以使用复合语句来定义变量,这样的变量只在本复合语句中有效.,局部变量,int max(int a,int b) int t; fun() int i; main() int m,n; ,m,n有效,a,b,t有效,i有效,1、含义:在所有的函数之外定义的变量称为外部变量(或全局变量).其作用范围是从变量定义的位置开始,直到本源文件的结束。示例: 2、要点: 3、例8-17、818、819:,全局变量,int p=1,q=1;/*定义全局变量p
14、,q*/ float f1(a) /*定义函数f1*/ int a; int b,c; char c1,c2; /*定义外部变量c1,c2*/ char f2(int x,int y)/*定义函数f2*/ int i,j; main() int m,n; ,全局 变量p,q的有 效范围,全局 变量c1,c2的有 效范围,39 / 54,(1)一个源文件可以包含一个或几个函数. (2)全局变量可以被本源文件的所有函数共享. (3)若想在全局变量的定义点之前引用,需要用关键字“extern”作引用说明. (4)全局变量的设置增强了函数间数据的联系.一个函数对全局变量的值的改变将会影响到其他的函数中
15、. (5)建议在只有必要时才设置全局变量. (6)当全局变量名与局部变量名相同时,则在局部变量的有效范围内全局变量不起作用.,全局变量使用要点,40 / 54,例8_17:有一个一维数组,内放10个学生成绩,写一个函数,求出平均分、最高分和最低分。(参见课本P185例8.15),例8_18:分析下面的程序写出结果.,运行结果;5,例8_19:分析下面的程序写出结果,运行结果:20,-15,2020,-15,20,1、变量按存在时间(生存期)分为:静态存储变量:在编译时分配固定的存储空间动态存储变量:在程序运行期间根据需要进行动态的分配存储空间 2、在c语言中将变量和函数的属性划分为:数据类型数
16、据的存储类别(数据在内存中的存储方法).如:static int a,b; 3、存储类别:自动变量(auto)静态变量(static)寄存器变量(register)外部变量(extern) 分别放在静态存储区和动态存储区.,变量和函数的存储类别,1、含义:函数中定义的变量不作特殊说明都为自动局部变量,存储在动态存储区。 2、用法:用关键字auto进行说明。如: int f(int a) auto int b=0,c=10; 3、要点: 可以省略auto关键字,当函数调用结束后,它们所占用的存储空间即被释放.,自动变量,45 / 54,1、含义:函数中的局部变量的值在函数调用结束后不消失而保留原
17、值。(即所占用的存储单元并不释放,下次直接使用) 2、用法:用static说明。例820 : 3、要点:,局部静态变量,例8_20:分析程序运行结果,运行结果: 7 8 9,1.局部静态变量存储在静态存储区,在程序的整个运行期间都不释放; 2.局部静态变量是在编译时赋初值的,即只赋值一次。 3.局部静态变量在定义时不赋初值,编译时系统自动赋初值0;而对于自动变量,如果不赋初值则它的值是一个不确定的值. 4.局部静态变量在函数调用结束后仍然存在,但只能被这个函数再次调用,不能被其他函数调用.,局部静态变量使用要点,1、含义:寄存器是计算机CPU的重要组成部分, 在c语言中允许将一些频繁使用的变量
18、存放在计算机的寄存器中,以节省运算时间,提高效率. 2、用法:用register说明。例821: 3、要点: 只有局部自动变量和形参可以作为寄存器变量。 一个计算机系统中的寄存器数目是有限的,不能定义任意多个寄存器变量。 局部静态变量不能定义为register变量。,寄存器变量,49 / 54,例8_21:求1n的阶乘,全局变量是在函数的外部定义的,存放在内存的静态存储区中,它可以被程序中的所有函数所引用. 1.允许其他文件中的函数引用.如果在一个文件中引用另一个文件中定义的全局变量,应当在需要引用的地方,使用extern进行说明.例822: 2.当在程序中希望全局变量只限于在本源文件使用不能
19、被其他的文件中的函数引用,可以在定义这个全局变量时用static进行说明,这时的static不代表静态的含义.,外部变量,51 / 54,例8_22:给定b的值,输入a,m的值,求a*b和am。,file1.c,file2.c,52 / 54,内部函数与外部函数,一、内部函数 格式:在函数定义时加上static.即: static 类型标识符 函数名(形参表) 要点:内部函数又称为静态函数这样的函数只限在所在的文件中. 二、外部函数 格式:在函数定义时加上extern即: extern 类型标识符 函数名(形参表) 要点:函数被冠以extern说明函数为外部函数,可以被其他文件中的函数所调用,当一个函数在定义时,未说明static时隐含的类型为extern. 三、例823:,53 / 54,例8_23:有一个字符串,内有若干个字符,今输入一个字符,程序将字符串中该字符删去,用外部函数实现。,file1.c,54 / 54,输出:abdefg,file2.c,file4.c,输入:abcdefgcc,file3.c,