C语言课件:第八章函数.ppt

上传人:牧羊曲112 文档编号:6504370 上传时间:2023-11-07 格式:PPT 页数:38 大小:478KB
返回 下载 相关 举报
C语言课件:第八章函数.ppt_第1页
第1页 / 共38页
C语言课件:第八章函数.ppt_第2页
第2页 / 共38页
C语言课件:第八章函数.ppt_第3页
第3页 / 共38页
C语言课件:第八章函数.ppt_第4页
第4页 / 共38页
C语言课件:第八章函数.ppt_第5页
第5页 / 共38页
点击查看更多>>
资源描述

《C语言课件:第八章函数.ppt》由会员分享,可在线阅读,更多相关《C语言课件:第八章函数.ppt(38页珍藏版)》请在三一办公上搜索。

1、1,第 8 章 函数,2,在进行程序设计时,程序员总是将复杂的问题进行分解,化整为零。编写一段小程序就能解决一个小问题,然后将这些小程序拼装起来就能解决非常大而复杂的问题。在 C 中,这些小程序统称为函数。,在 C 中,由系统提供的函数放在函数库中供用户选用,以减少重复编写程序模块的工作量。,所有函数都是平行的,相互独立不能嵌套,但可以相 互调用。,C 函数分标准函数(库函数)和自定义函数。,C 函数本身分有参函数和无参函数。,8.1 概述,第 8 章 函数,3,8.2 函数定义的一般形式,1无参函数的定义形式,类型标识符 函数名()说明部分;语句;,无参函数一般不需要返回函数值,可以省略类型

2、标识符。,2有参函数的定义形式,类型标识符 函数名(形式参数表)形式参数说明;说明部分;语句;,4,例:int max(x,y)int x,y;/形式参数说明/int z;/函数体中的说明部分/z=xy?x:y;return(z);,类型说明符 函数名(),“空函数”什么操作也不做。其作用是在此处留一函数的位置,以便将来扩充功能之用。函数名也在将来换取实际的函数名。,3“空函数”,5,8.3 函数参数和函数的值,1形式参数和实际参数,例8.2 从键盘输入两个数,输出其中较大的一个。main()int a,b,c;scanf(“%d,%d”,6,注意:,形参变量在被调用前不占用存储单元;在被调用

3、结束 后,形参所占存储单元亦被释放。,实参可以是常量、变量或表达式。,必须指定形参类型,且必须与实参的类型一致。,实参对形参的数据传递是“值传递”。即单向传递,不 能逆传。,可以在形参表中直接说明形参类型。,如:,int max(int x,int y);,float fun(int a10,int n);,7,2函数的返回值,函数的返回值是通过return语句获得的。当不需返 回函数值时,可省去return语句。,return语句的后面可以有括号,也可以没有。,如:,return z;return(z);,return语句的后面可以是变量,也可以是表达式。,如:,return(x y?x:y

4、);,return语句返回值的类型应与该函数的类型一致。否则以函数类型为准。,8,若函数中没有return语句,则该函数被调用后也会带 回不确定的值。,int a,b,c;a=printstar();b=print_message();c=printstar();printf(“%d,%d,%dn”,a,b,c);,输出的a,b,c的值将是各个被处理的字符串的长度。,为了明确表示不需要函数返回值,可以用“void”定义 函数为“无类型”。此时,不得使用 a=printstar()之 类的语句。,凡不需要返回值的函数,一般均定义为“void”类型。,如:,9,8.4 函数的调用,1函数调用的一般

5、形式,函数名(实参表),说明:,对于无参函数,尽管没有“实参表”,但也不得省略 括号。,“实参表”中的参数之间用逗号分开。,实参与形参之间的个数及类型必须一一对应。,对实参求值的顺序是自左至右还是自右至左,视具体 的系统而定。Turbo C 和 MS C 是按自右至左的顺 序求值。,10,例8.4main()int i=2,p;p=f(i,+i);printf(“%d”,p);int f(a,b);int a,b;int c;if(a b)c=1;else if(a=b)c=0;else c=1;return(c);,输出结果:0,b 的值为3,a 的值为3,11,2函数调用的方式,调用函数,

6、可以有如下三种方式:,将函数调用作为一个语句。,如:,printf(“MS C programming”);,gets(s);,将被调用的函数写在表达式中。,如:,c=2 max(a,b);,注意:被调用函数 max 必须有确定的返回值。,将函数调用作为一个函数的实参。,如:,m=max(max(a,b),c);,3对被调用函数的说明,在一个函数中调用另一个函数时:,如果被调函数为库函数,则应在文件开头用“#include”命令 声明相应的“头文件”。,如:,#include“stdio.h”#include“math.h”,12,如果被调函数为自定义函数且其定义在主调函数定义之后,则 应在主

7、调函数中说明其类型。,类型标识符 被调函数名();,如:float add();,其语句形式为:,如果被调函数为自定义函数且其定义在主调函数定义之前,则 在主调函数中可不必说明其类型。因为编译程序已知道其类型,如果被调函数的值是整型或字符型,可不必说明类型,系统自 动按整型说明。,如果在所有被调函数定义之前、在文件的开头、在函数的外部 已对被调函数作了类型说明,则在各主调函数中可不必说明其 类型。,如:,char letter();float f();int i();main(),/主调函数中不必说明它所调用的函数的类型/,13,例:编程求11999之间的数 m,而 m、m2 和 m3 均是回

8、文数。,如:m=11、m2=121、m3=1331,。,#include“stdio.h”main()long int m;for(m=11;m1000;m+)if(fun(m),14,8.5 函数的嵌套调用,C 语言函数的定义都是相互平行、独立的,不能嵌套定义。但可以嵌套调用函数。所谓函数的嵌套调用就是在被调用的函数中又调用另外的函数。,Main()x=root(x1,x2);/*调用root函数*/,Float root(float y1,float y2)y1=f(x);/*调用f 函数*/,15,8.6 函数的递归调用,自己调用自己,递归一次,分配一次存储单元,返回时,一层一层返回;,

9、2 递归程序示例,1 递归的概念,递归分为:直接递归:函数中自己调用自己;间接递归:在调用其他函数中调用自己。,16,例8.7 有5人排成一队,从最后一人开始,其年龄均比 前面的人大2岁,而最前面的人年龄是10岁,问 最后一人的年龄是多少岁?,main(),age(5),age(4)+2,age(n)n=5,age(3)+2,age(n)n=4,age(2)+2,age(n)n=3,age(1)+2,age(n)n=2,age(1),age(n)n=1,age(1)=10,age(2)=12,age(3)=14,age(4)=16,age(5)=18,输出age(5),age(n)int n;

10、int c;if(n=1)c=10;else c=age(n1)+2;return(c);,main()printf(“%dn”,age(5);,运行结果:18,17,函数的递归调用利用了堆栈技术。在本例中:,Age(5),Age(51)+2,Age(41)+2,Age(31)+2,Age(21)+2,10+2=12,12+2=14,14+2=16,16+2=18,18,Age(21)+2,Age(31)+2,Age(41)+2,Age(51)+2,Age(5),Age(5),Age(51)+2,Age(41)+2,Age(31)+2,Age(21)+2,入栈,出栈,出栈结果,18,例:把一非

11、零的整数倒序打印,main()int aa();int n;scanf(“%d”,19,例:读入一串字符,并倒序打印,main()char abc();abc();char abc()char ch;scanf(“%c”,20,例:求两个数的最大公约数,main()int gcd(a,b);int n,m;scanf(“%d%d”,21,8.7 数组作为函数参数,1数组元素作函数实参,用法与变量参数相同,是单向传递,即“值传递”方式。,例:,main()y=fun(a0,a1.a2);float fun(float a,float b,float c)float sum,aver;sum=a+

12、b+c;aver=sum/3.0;return(aver);,22,8.7 数组作为函数参数,2数组名作函数实参,此时,实参数组名和形参数组名都应分别在各自所在的函数中定义;采取“地址传送”方式,即:把实参数组的起始地址传给形参数组,这样,实参数组和形参数组共占同一段内存单元。,23,例:,main()float fun1(float x3);float a3=80.0,90.0,100.0;float ave;ave=fun1(a);printf(“%fn”,ave);float fun1(float x3)float sum,aver;sum=x0+x1+x2;aver=sum/3.0;r

13、eturn(aver);,24,例:用函数调用实现字符串的复制。,void copy_string(from,to)char from,to;int i=0;while(from i!=0)to i=from i;i+;to i=0;main()char a=“I am a teacher.”;char b=“you are a student.”;copy_string(a,b);printf(“string_a=%snstring_b=%sn”,a,b);,运行结果:string_a=I am a teacher.string_b=I am a teacher.,25,8.8 局部变量和全

14、局变量,1局部变量,在一个函数内部定义的变量,只能在本函数内使用和有效,称为“局部变量”。,主函数main中定义的变量,也只能在主函数内使用和有效。,不同函数中可以使用相同名字的变量,且互不干扰。,形式参数也是局部变量,也只能在所在函数内使用和有效。,可以在一个函数内的复合语句中定义变量,且这些变量只 在本复合语句中有效。,这种复合语句也称为“分程序”或“子模块”。,2全局变量,在函数(包括main函数)外定义的变量为外部变量,称为“全局变量”。全局变量的有效范围为从定义变量的位置开始到本源文件结束。,26,全局变量增加了函数间数据联系的渠道。由于同一文件中的所 有函数都能引用全局变量的值,当

15、需要从一个函数中带回多个 值时,就能克服函数调用只能返回一个值的局限性。,如无必要,不要使用全局变量。因为全局变量既降低程序的清 晰性和函数的通用性,且又在程序的全部执行过程中都占用存 储空间。,在文件开头定义的外部变量才可在整个文件范围内使用,若在 定义点之前的函数需引用外部变量,则可用关键字“extern”作“外部变量说明”。,注意:外部变量定义和外部变量说明并不是同一回事。外部变量的定义只能有一次,它的位置在所有函数之外。而同一程序中的外部变量说明可以有多次,它的位置在函数之内(哪个函数要用就在哪个函数中说明)。系统根据外部变量的定义(而不是根据外部变量的说明)分配存储单元。对外部变量的

16、初始化只能在“定义”时进行,“extern”只是申明该变量是一个已在外部定义过的变量而已。,如果在同一源文件中,外部变量与局部变量同名,则在局部变 量的作用范围内,外部变量不起作用。,27,例:#include“stdio.h”main()int a=1,b=2,c=3;a+;c+=b;int b=4,c;c=2b;a+=c;printf(“%d,%d,%dn”,a,b,c);printf(“%d,%d,%dn”,a,b,c);,输出结果:10,4,810,2,5,28,8.9 变量的存储类别,1动态存储方式与静态存储方式,静态变量在程序的运行期间占用固定的存储空间,直到程序的终止而释放;动态

17、变量是在程序的运行期间随着函数的调用随时动态地占用和释放存储空间。存储方式是根据变量的存储类别决定的。,C的存储类别有四种:,自动的(auto)静态的(static)、寄存器的(register)外部的(extern)。,29,8.9 变量的存储类别,1)自动变量(auto),自动变量是局部变量,2局部变量的存储方式,函数中的局部变量若未专门说明,都是由编译系统自 动动态分配存储空间,这类局部变量称为自动变量,其类型说明前不论是否有关键字“auto”,都属于动态 存储类别。,自动变量赋值之前,值不确定,对同一函数的两次调用之间,自动变量的值不保留,定义式:auto数据类型 变量名=初值表达式1

18、,,30,8.9 变量的存储类别,2)静态变量(static):局部变量,2局部变量的存储方式,静态变量的存储空间在程序 的整个运行期间时固定,定义式:static 数据类型 变量名表,若希望被调函数在结束后,其局部变量占用的存储空间不释放,以便保留其变量的值,用于下次调用该函数,则用“static”说明为“局部静态变量”。,静态变量的初始化是在编译时进行的。,31,局部静态变量在静态存储区分配存储单元,在程序的整个运行 期间都不释放。而动态变量在动态存储区分配存储单元,函数 调用结束后即释放。,局部静态变量在编译时只赋初值一次,以后每次被调用时不再 重新赋值而只保留前次被调用结束时的值。动态

19、变量赋初值不 是在编译时而是在函数被调用时进行的,函数每次被调用时重 新赋值,相当于赋值语句。,静态变量若未赋初值,则在编译时自动赋初值0(数值型)或空字 符(字符型)。而动态变量若未赋初值,则其值是不确定的。,只有将数组定义为全局变量或静态变量时才能赋初值。但应注 意,如果数组的值在函数被调用过程中改变了,则影响下一次 调用时的初值。,虽然局部静态变量在函数被调用结束后其值仍然存在,但其它 函数是不能引用的。,32,8.9 变量的存储类别,3)寄存器变量(register):局部变量,注意:只有局部自动变量和形式参数可作为 是寄存器变量;静态变量和全局变量 均不行。,2局部变量的存储方式,特

20、点:速度快,一般把使用频率较高的变量 定义为寄存器变量。,定义式:register 数据类型 变量名表,33,例8.18 打印 1 到 5 的阶乘值。,int fac(n)int n;static int f=1;f=f n;return(f);main()int i;for(i=1;i=5;i+)printf(“%d!=%dn”,i,fac(i);,3全局变量的存储方式,在文件开头用extern作说明,可以引用另一个文件中定义的全局变量。但用static说明的全局变量不能被其它文件引用。,34,int m=1,n=4;float f1(a)int a;int b,c;char ch1,ch2

21、;char f2(x,y)int x,y;int k,j;main()extern int p,q;,例:,35,全局变量的作用范围:,在文件开头定义的外部变量,在整个文件中均可以引用;,不在文件开头定义的外部变量,从定义点到文件结束。,设置全局变量的作用:,增强函数间的联系渠道;,使用全局变量可以减少函数实参和形参的个数,一个源文件中,外部变量与局部变量重名时,则全局变量应扣除去局部变量所在的函数范围。,全局变量的使用降低了程序的通用性,一般建议不必要时不用全局变量。,36,int m=1,n=4;float f1(a)int a;int b,c;char ch1,ch2;char f2(x

22、,y)int x,y;int k,j;main()extern int p,q;,例:,37,File1.cInt a;Main(),File2.cextern int a;func(n)int n a=a*n;,虽然在file2.c 对“a”用extern 说明了,但也不能引用file1.c中的“a”,还需在extern int a;之前加上:#include“file1.c”或在file1.c中的 int a;之前加上:#include“file2.c”,38,8.10 内部函数和外部函数,就函数的本质而言都是全局的。但根据其是否能被其它文件所调用,将它们区分为内部函数和外部函数。,1内部函数,如果一个函数只能被本文件的其它函数所调用,则将它称为内部函数。可以用“static”将函数定义为内部函数。,如:,static int fun(a,b);,同静态变量一样,内部函数只局限于本文件内使用,因而不会和其它文件中的同名函数发生冲突。,2外部函数,在定义函数时,如果在其类型说明前冠以extern,则表示此函数为外部函数。,如:,extern int fun(a,b);,外部函数可以被其它文件所使用。如果省略extern,则隐含该函数为外部函数。,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号