




已阅读5页,还剩65页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,第六章函数,1/70,2,6.1概述6.2函数6.3函数的嵌套调用6.4函数的递归调用6.5数组作为函数参数6.6语言的库函数,2/70,6.1概述,#includestdio.hvoidstars(intn);voidprint_message();main()stars(20);print_message();stars(20);voidstars(intn)inti;for(i=1;i0),intpower(intx,intn)inti,mul=1;for(i=1;iy?x:y;return(z);,intmax(x,y)intx,y;intz;z=xy?x:y;return(z);,10/70,11,6.2.2函数的参数,主调函数和被调函数之间通过函数参数进行数据传递。,一、形参和实参,1、定义:,形式参数:函数定义时,函数名后面括号内的参数称为形式参数。,实际参数:函数调用时,函数名后面括号内的参数称为实际参数。实参可以是常量、变量、表达式或具有返回值的函数调用表达式。,2、例:,#includeintmax(intx,inty);voidmain()inta,b,c;scanf(%d%d,intmax(intx,inty)intz;z=xy?x:y;return(z);,11/70,12,二、关于形参与实参的说明:,1、在进行函数调用前,函数的形参并不占有内存单元;只有在函数被调用时,其形参才被分配内存单元,并在调用结束后释放形参所占的内存单元。,2、形参只能是变量,而实参可以是常量、变量或表达式,但要求它们有确定的值。调用时将实参的值赋给形参。,max(3,a+b);,3、在定义函数时,必须指定形参的类型。,intmax(intx,inty)intz;z=xy?x:y;return(z);,4、实参与形参的个数应一样,类型应一致或赋值兼容。,12/70,13,5、语言规定,实参对形参的数据传递是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。,a,2,b,5,x,y,2,5,voidfun(inti,intj)intx=7;printf(i=%d,j=%d,x=%dn,i,j,x);main()inti=2,x=5,j=7;fun(j,6);printf(i=%d,j=%d,x=%dn,i,j,x);,i=7,j=6,x=7,i=2,j=7,x=5,eg602.c,13/70,14,三、例:,#includevoidsum(intx,inty,intz)z=x+y;main()inta=1,b=2,c=0;sum(a,b,c);printf(c=%dn,c);,c=?,14/70,15,6.2.3函数的返回值,1、函数的返回值是通过函数中的return语句获得的。return语句将被调用函数中的一个确定值带回主调函数中去。,return语句的一般形式是:,return(表达式);,或:return表达式;,或:return;,、若return后面带表达式,首先计算表达式的值,表达式的值就是所求的函数值。表达式的类型必须与函数首部说明的类型一致。,intmax(intx,inty)intz;z=(xy)?x:y;return(z);,return(xy?x:y);,returnxy?x:y;,15/70,16,、一个函数可以含有多个return语句,但当执行到其中一个return语句就返回主调函数。,intisPrime(intm)inti,k;k=sqrt(m);for(i=2;i=k;i+)if(m%i=0)return(0);return(1);,、一个函数可以没有return语句,此时当函数执行到最后一个界限符“”时返回主调函数。,2、函数值的类型:应当在定义函数时指定函数的类型。,intmax(intx,inty),charletter(charc1,charc2),doublemin(intx,inty),语言规定,凡不加类型声明的函数,自动按int型处理。,max(intx,inty),intmax(intx,inty),16/70,17,3、在定义函数时,对函数值声明的类型一般应该和return语句中的表达式类型一致;若不一致,则以函数类型为准(自动转换)。,4、对于有返回值的函数,若return语句后面没有表达式,或没有return语句,此时带回一个不确定的返回值。,stars(intn)inti;for(i=1;iy?x:y;return(z);,eg604.c,23/70,24,3、如果被调用函数出现在主调函数之前,可以不必进行声明。,intmax(intx,inty)main()c=max(a,b);,4、如果已在所有函数定义之前,在函数的外部已作了函数声明,则在各个主调函数中不必对所调用的函数再做声明。,#includestdio.hvoidstars(intn);voidprint_message();main()stars(20);print_message();stars(20);voidstars(intn)voidprint_message(),5、除以上三种情况,都应对所调用函数作类型声明,否则编译时出现错误。,24/70,25,三、例:,1、由键盘输入三个整数a、b、c,编写函数,找出绝对值最大的数并返回。在主函数中进行输入输出。,eg605.c、eg606.c,2、编写函数,将字符ch打印row行col列,函数原型为:voidprint(charch,introw,intcol);,for(i=1;i=row;i+)for(j=1;j=col;j+)putchar(ch);printf(n);,25/70,6.3函数的嵌套调用,语言的函数定义都是互相平行的、独立的,即不允许嵌套定义函数;但是,可以嵌套调用函数,即程序在调用一个函数的过程中,该被调函数又可以调用其它函数。,下图表示函数的嵌套调用:,26/70,例:求1!+2!+3!+n!,#includevoidmain()floatsum(int);floatadd;intn;scanf(%d,floatsum(intn)floatfac(int);inti;floats=0;for(i=1;i0):);scanf(%d,eg608.cpp,31/70,函数调用过程:,main()n=5;print(f(5);,longf(5)longy;y=5*f(4);,longf(4)longy;y=4*f(3);,longf(3)longy;y=3*f(2);,longf(3)longy;y=3*f(2);,longf(2)longy;y=2*f(1);,longf(1)longy;y=1;,return(1);,return(2);,return(6);,return(6);,return(24);,return(120);,32/70,三、递归的条件:,1、须有完成函数任务的语句;,longf(intn)longy;if(n=1)y=1;elsey=n*f(n-1);return(y);,2、一个确定是否能避免递归调用的测试;,3、一个递归调用语句;,该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。,4、先测试,后递归调用。,在递归函数定义中,必须先测试,后递归调用。也就是说,递归调用是有条件的,满足了条件后,才可以递归。,longf(intn)longy;y=n*f(n-1);if(n=1)y=1;return(y);,33/70,四、递归的特点:,1、递归调用不是重新复制该函数,每次调用它时,新的局部变量和形参会在内存中重新分配内存单元,并以新的变量重新开始执行;每次递归返回时,当前调用层的局部变量和形参被释放,并返回上次调用自身的地方继续执行;,2、递归调用一般并不节省内存空间,因为每次调用都要产生一组新的局部变量,从而不破坏上层的局部变量;,3、递归调用一般并不能加快程序的执行速度,因为每次调用都要保护上层局部量(现场),而返回时又要恢复上层局部量,占用执行时间;,4、递归函数中,必须有结束递归的条件;,5、递归调用的优点是能实现一些迭代算法难以解决的问题。,34/70,6.5数组作为函数参数,6.5.1数组元素作为函数参数6.5.2一维数组作为函数参数6.5.3多维数组作为函数参数,35/70,6.5.1数组元素作为函数参数,从语法角度看,实参可以是表达式形式,如常量、变量和由运算符连结的表达式形式。而数组元素可以是表达式的组成部分,所以它可以作为函数的实参;它与形参之间是以“值传递”的形式进行参数传递,即单向传递。,例:有两个数组a、b,各有10个元素,将它们对应地逐个相比,分别统计出两个数组相应元素大于、等于、小于的次数。,for(i=0;iy)flag=1;elseif(x=y)flag=0;elseflag=-1;,return(flag);,if(result=1)m+;elseif(result=0)n+;elsek+;,eg609.cpp,36/70,6.5.2一维数组作为函数参数,数组作为函数参数,即用数组名作为函数实参,要求实参和形参都应为数组名。此时主调函数将实参数组的起始地址传递给被调函数的形参数组,而不是传递数组元素的值。,例:有一个一维数组score,内放10个学生的成绩,求平均成绩,floatscore10;,aver=average(score);,floataverage(floatarray10),inti;floataver,sum=0.0;for(i=0;i10;i+)sum+=arrayi;aver=sum/10.0;return(aver);,eg610.cpp,37/70,说明:,1、用数组名作函数参数,应在主调函数和被调函数中分别定义数组,而不能只在一方定义,被调函数是在形参表中进行定义;,floatscore10;,aver=average(score);,floataverage(floatarray10),2、形参数组和实参数组的大小可一致可不一致;语言编译时对形参数组大小不作检查,只将实参数组的首地址传给形参数组;,3、形参数组可以不指定大小,仅给出数组类型、数组名和一对方括号,另设一个参数传递数组的实际长度;,floataverage(floatarray,intn),aver=average(score,10);,eg611.cpp,38/70,4、实参数组与形参数组类型应一致,否则出错;,5、数组名作函数实参时,不是把数组的值传递给形参,而是把实参数组的起始地址传递给形参数组;这样,形参数组和实参数组就共占同一段内存单元,即表示同一个数组。因此,形参数组元素的变化等同于实参数组元素的变化;,6、从传递方式来看,应理解为“传值”方式,即传递的是数组名所代表的值。,39/70,6.5.3多维数组作为函数参数,1、形参数组定义时可以指定每一维的大小,也可省略第一维的大小说明(但不能省略第二维及其它高维的大小说明),intfun(intarray34),或:intfun(intarray4),但不能写成:intfun(intarray),也不能写成:intfun(intarray3),即不能指定第一维而省略第二维;编译器不检查第一维的大小,但将对高维的大小进行检查。,2、实参数组可以大于形参数组;,intscore510;,intarray310;,此时实参中只有前面数据起作用。,40/70,例:求3行4列二维数组中的最大元素,intmax_value(intarray4),inti,j,max;max=array00;for(i=0;imax)max=arrayij;reutrn(max);,eg613.cpp,41/70,6.6语言的库函数,1、库函数不是语言本身的组成部分。它是编译系统生产厂家开发的函数,存放在库文件中;用户可以根据需要调用这些函数。,2、各编译系统所提供的库函数不尽相同,但一般都提供了ANSIC标准所建议的数百个库函数。,3、标准库函数包括输入输出函数、字符和字符串函数、数学函数、内存管理函数、进程管理函数、时间函数等。,4、使用库函数时应用#include命令将有关头文件包含在程序中。,5、除标准库函数外,各编译系统还提供了种类和数量繁多的非标准库函数,如图形函数、与系统有关的函数等。,42/70,6.7作用域与存储类别,6.7.1相关概念6.7.2局部变量与全局变量6.7.3变量的存储类别6.7.4函数的作用域和存储类别6.7.5存储类别小结,43/70,6.7.1相关概念,一、作用域,定义:指变量能够起作用的程序范围。,如果一个变量在某源程序文件或某函数范围内有效,则称该文件或函数为该变量的作用域。,二、生存期,定义:指变量在内存中存在的时间范围。,变量在整个程序的运行时间都存在,变量只在某个函数的执行过程中才存在,44/70,6.7.2局部变量和全局变量,一、局部变量,1、定义:在函数内部定义的变量,2、例:,intf1(inta)intv1,x;intf2(void)intv2,x,y;main()intm,y;,a、v1、x的有效范围,v2、x、y的有效范围,m、y的有效范围,45/70,3、说明:,、主函数main中定义的变量也只在主函数中有效,其它函数不能引用;,、不同函数中可以使用相同名字的变量,它们代表不同的对象,占用不同的内存单元,互相独立;,、形式参数也是局部变量;,、可以在复合语句中定义变量,其作用域只是本复合语句。,main()inta,b;intc;c=a+b;,c在此范围内有效,a、b在此范围内有效,46/70,voidmain()inti,a=0;for(i=1;i=2;i+)inta=1;a+;printf(i=%d,a=%dn,i,a);printf(i=%d,a=%dn,i,a);,i=1,a=2,i=2,a=2,i=3,a=0,二、全局变量,1、定义:在函数外部定义的变量,又称为外部变量,全局变量可以为本文件中其它函数所共用,其有效范围为:从定义变量的位置开始到本源文件结束。,eg614.cpp,47/70,2、例:,#includeintp=1,q=5;floatf1(inta)intb,c;charc1,c2;charf2(intx,inty)inti,j;.main()intm,n;,全局变量p、q的作用域,全局变量c1、c2的作用域,48/70,3、说明:,、全局变量增加了函数间的数据联系;,、尽量少使用全局变量(除非在必要时);,各模块间的相互联系、相互影响太多,降低了模块的独立性;会降低程序的清晰性,因为各个函数都有可能改变全局变量的值,需要时刻记住变量的当前值,编程时候容易出错。,#includeintk;voidshow()for(k=1;ky?x:y;return(z);voidmain()externinta,b;printf(%d,max(a,b);inta=13,b=-8;,eg617.cpp,51/70,6.7.3变量的存储类别,一、存储空间的划分,程序区:用于存放程序编译后形成的可执行代码(执行时装入),静态存储区:用于存放程序中的静态数据,如全局变量等,动态存储区:用于存放程序中的动态数据,如函数形参、局部变量、函数调用时的现场保护和返回地址等,静态数据说明时在静态存储区中分配存储单元并在程序执行过程中始终占用该单元,直到程序结束才释放;动态数据在函数开始执行时分配动态存储空间,函数结束时释放这些空间。,的存储类别有四种:auto、static、register和extern。,52/70,二、局部变量的存储方式,1、函数中的局部变量,如不做专门的声明,都是动态分配存储空间的,存储在动态存储区中;用关键字auto作存储类型的声明,这类变量称为自动变量。,autointb,c=3;,autofloatf;,通常auto被省略,auto不写则隐含确定为“自动存储类别”,intb,c=3;floatf;,2、局部静态变量,函数编译时在静态存储区分配存储单元,函数调用结束后不释放存储单元,即在整个程序的运行中不释放存储单元。用static声明该变量为“局部静态变量”。,staticints;,staticcharch;,53/70,voidf(intc)inta=0;staticintb=0;a+;b+;printf(%d:a=%d,b=%dn,c,a,b);voidmain()inti;for(i=1;i=3;i+)f(i);,1:a=1,b=1,2:a=1,b=2,3:a=1,b=3,说明:,、静态局部变量采用静态存储方式,而自动变量采用动态存储方式;,eg618.cpp,54/70,、若对变量赋初值,对于静态变量,只执行一次,再次调用函数时不再赋初值而保留上次函数调用结束时的值;而对于自动变量,每次调用都要重新分配内存单元并赋初值;,、若不对变量赋初值,对于静态变量系统自动赋缺省值;而对于自动变量,只分配存储单元,其值不确定。,、虽然静态局部变量在函数调用结束后仍占存储单元,但由于是局部变量,其它函数不能引用它。,适用范围:,、需要保留函数上一次调用结束时的值;(占用永久性的存储空间),、对于数组进行初始化,通常定义为静态存储类别。,55/70,3、寄存器(register)变量,为了减少从内存中存取变量值的时间,语言允许将局部变量的值放在寄存器中;用关键字register声明。,intfac(intn)registerinti,f;for(i=1;i=n;i+)f=f*i;return(f);,说明:,、只有局部自动变量和形参可以定义为寄存器变量,关键字register不能省略;,、不能定义太多的寄存器变量,因为寄存器数量有限,太多无效(将自动按自动变量处理)。,56/70,三、全局变量的存储方式,全局变量是在函数外部定义的,存放在静态存储区,在程序的整个运行过程中占用存储单元,生存期为整个程序的运行期间。,全局变量有两种存储类别:static和extern,用来对其作用域进行限制或扩充。,1、如果想在定义之前的函数中引用全局变量,则在函数中用关键字“extern”作“外部变量声明”,在函数内部,从声明之处起,可以使用它们。,voidmain()externinta,b;printf(%d,max(a,b);inta=13,b=-8;,57/70,2、如果一个程序由多个源程序文件组成,那么一个某文件中的函数能否引用另一个文件中的全局变量,有两种情况:,、在一个文件中要引用另一文件中定义的全局变量,要在引用它的文件中用extern作声明。,在文件file1.c中定义的变量a,在文件file2.c中引用,引用前加上extern进行声明。,58/70,、全局变量仅限于被本文件中的函数引用,其它文件不能使用。定义全局变量时用static进行声明。,加上static,限制了a的作用域,在file2.c中引用失败;但不管是否加上static,a都按静态存储方式存放。,59/70,6.7.4函数的作用域和存储类别,一、内部函数,如果一个函数只能被本文件中其它函数所调用,称为内部函数(或静态函数)。定义时在函数类型前加static。,staticintfac(intx),二、外部函数,定义时在函数类型前加关键字extern。,externintfac(intx),语言规定,如果在定义函数时省略extern,则隐含为外部函数。,说明:在需要调用此函数的文件中,要用extern声明所调用函数的原型。,60/70,6.7.5存储类别小结,1、数据的两种属性:,数据类型,存储类别,autofloata;,staticintb;,registercharc;,externintd;,(声明变量是已定义的变量),2、从作用域分:,局部变量,全局变量,自动变量,静态局部变量,寄存器变量,形参,静态全局变量,非静态全局变量,61/70,3、从生存期分:,动态存储,静态存储,自动变量,寄存器变量,形参,静态局部变量,静态全局变量,非静态全局变量,4、从存放位置分:,内存的静态存储区:,内存的动态存储区:,CPU中的寄存器:,静态局部变量,静态全局变量,外部变量,自动变量,形参,寄存器变量,62/70,6.8本章要点小结,函数定义的形式:,类型名函数名(类型名形参1,类型名形参2,)变量定义部分语句部分,函数调用表达式:,函数名(实际参数表),函数声明的形式为:,类型名函数名(类型名形参1,类型名形参2,);,63/70,64,函数的嵌套调用和递归调用;,数组名作为函数参数;,局部变量的全局变量;,变量的作用域和存储类别;,64/70,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 甲状腺功能亢进芯片技术-洞察及研究
- 2025年墙纸设计与生产定制合同标准模板
- 2025版投标员实习期间职业道德教育合同
- 2025年健康养生中心经营管理合同范本
- 2025年度房抵工程款光伏组件生产项目合作协议
- 2025年度豪华学区二手房买卖协议
- 2025版全新杂物间租赁及物业管理服务合同文本
- 2025年度企业人才引进与委托培训一体化项目合同
- 2025年船舶保险与运输合同
- 2025二手楼赎楼担保与房产交易合同
- 2025年北京高端商务车租赁及全程安全保障合同
- 2025版电商平台入驻及佣金分成合作协议
- 中国黄金集团招聘面试经典题及答案
- 2025年智能家居产业互联互通标准与产业发展现状及问题研究报告
- 2025年领导干部政治理论知识必考题库及答案
- 2025年提取公积金租房合同范本
- 2025年湖南省社区工作者招聘考试(公共基础知识和写作)历年参考题库含答案详解(5套)
- 2025年部编版新教材语文七年级上册教学计划(含进度表)
- 湖北省武汉市武昌区重点名校2026届中考语文全真模拟试题含解析
- 2.4抽象函数的周期性与对称性-讲义(原卷版)
- 喷粉挂钩管理办法
评论
0/150
提交评论