1第六章函数1/7026.1概述6.2函数6.3函数的嵌套调用6.4函数的递归调用6.5数组作为函数参数6.6C语言的库函数2/70§6.1概述#includestdio.hvoidstars(intn);voidprint_message();main(){stars(20);print_message();stars(20);}voidstars(intn){inti;for(i=1;i=n;i++)putchar('*');putchar('\n');}voidprint_message(){printf(Howdoyoudo!\n);}/*函数stars、print_message的声明*//*main函数的定义*//*对stars、print_message函数调用*//*定义stars函数*//*定义print_message函数*/eg601.c3/70说明:1、一个C程序可以由一个或多个源程序文件组成。2、C程序的执行从main函数开始,由主函数调用其它函数,其它函数也可以相互调用,程序流程最后回到main函数,在main函数中结束整个程序的运行。3、一个(主调)函数可以多次调用多个(被调)函数。同一个函数也可以被一个或多个(主调)函数调用任意多次。下图说明一种调用关系:mainabcfdefghid4/7054、main函数是系统定义的,只能由系统调用。5、所有函数在定义时都是平行的,相互独立(一个函数并不从属于另一个函数),即函数不能嵌套定义,但可以相互调用。6、函数分类使用情况库函数(标准函数):由系统提供,用户不必自己定义,可以直接使用用户自定义函数:解决用户的专门需要函数形式无参函数:主调函数与被调函数之间没有数据传递有参函数:主调函数与被调函数之间有数据传递任务情况带返回值不带返回值5/70§6.2函数6.2.1函数的定义6.2.2函数的参数6.2.3函数的返回值6.2.4函数的调用6.2.5函数的声明6/7076.2.1函数的定义1、函数定义的一般形式:函数类型说明符函数名(类型名形式参数1,类型名形式参数2,……){变量说明部分语句部分}2、说明:①、函数类型说明符:说明函数返回值的类型。intmax(intx,inty){……}voidstars(intn){……}②、函数名:是用户给函数起的名字,需符合标识符的规定。③、形式参数表:说明参数的个数和类型。7/708④、变量说明:说明函数中用到的除形参以外的其它变量。⑤、语句部分:为了完成特定的功能而设计的一个或多个语句。3、例:①、打印一行信息“Howdoyoudo!”函数的定义:voidprint_message(){printf(Howdoyoudo!\n);}②、求整数x的n次幂(n0)intpower(intx,intn){inti,mul=1;for(i=1;i=n;i++)mul=mul*x;return(mul);}8/7094、注意:①、C语言中不允许一个函数内定义另一个函数,一个C程序可以由多个函数组成,但所有函数在书写时都是平行的,不能嵌套。main(){……}voidstars(intn){……}voidprint_message(){……}②、C程序中,允许有空函数存在。定义形式为:函数类型说明符函数名(){}其它函数可以调用空函数,调用时什么也不做。9/7010③、还有一种老式的函数定义:函数类型说明符函数名(形式参数1,形式参数2,……)形式参数说明;{变量说明部分语句部分}intmax(intx,inty){intz;z=xy?x:y;return(z);}intmax(x,y)intx,y;{intz;z=xy?x:y;return(z);}10/70116.2.2函数的参数主调函数和被调函数之间通过函数参数进行数据传递。一、形参和实参1、定义:形式参数:函数定义时,函数名后面括号内的参数称为形式参数。实际参数:函数调用时,函数名后面括号内的参数称为实际参数。实参可以是常量、变量、表达式或具有返回值的函数调用表达式。2、例:#includestdio.hintmax(intx,inty);voidmain(){inta,b,c;scanf(%d%d,&a,&b);c=max(a,b);printf(Max=%d.\n,c);}intmax(intx,inty){intz;z=xy?x:y;return(z);}11/7012二、关于形参与实参的说明:1、在进行函数调用前,函数的形参并不占有内存单元;只有在函数被调用时,其形参才被分配内存单元,并在调用结束后释放形参所占的内存单元。2、形参只能是变量,而实参可以是常量、变量或表达式,但要求它们有确定的值。调用时将实参的值赋给形参。max(3,a+b);3、在定义函数时,必须指定形参的类型。intmax(intx,inty){intz;z=xy?x:y;return(z);}4、实参与形参的个数应一样,类型应一致或赋值兼容。12/70135、C语言规定,实参对形参的数据传递是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给实参。在内存中,实参单元与形参单元是不同的单元。a2b5xy25x45y56a2b5voidfun(inti,intj){intx=7;printf(i=%d,j=%d,x=%d\n,i,j,x);}main(){inti=2,x=5,j=7;fun(j,6);printf(i=%d,j=%d,x=%d\n,i,j,x);}i=7,j=6,x=7i=2,j=7,x=5eg602.c13/7014三、例:#includestdio.hvoidsum(intx,inty,intz){z=x+y;}main(){inta=1,b=2,c=0;sum(a,b,c);printf(c=%d\n,c);}c=?14/70156.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/7016②、一个函数可以含有多个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)C语言规定,凡不加类型声明的函数,自动按int型处理。max(intx,inty)intmax(intx,inty)16/70173、在定义函数时,对函数值声明的类型一般应该和return语句中的表达式类型一致;若不一致,则以函数类型为准(自动转换)。4、对于有返回值的函数,若return语句后面没有表达式,或没有return语句,此时带回一个不确定的返回值。stars(intn){inti;for(i=1;i=n;i++)putchar('*');putchar('\n');}x=stars(10);printf(%d,x);5、为了明确表示“不带回值”,可以用void定义“无类型”(或称“空类型”)。eg603.cvoidstars(intn)17/70186.2.4函数的调用一、一般形式:1、函数调用的一般形式为:函数名(实际参数1,实际参数2,……)2、说明:①、若调用无参函数,则无实参表列,但括弧不能省略;②、如果实参表列包含多个实参,则各参数间用逗号隔开;③、实参与形参的个数应相等,类型应一致;④、实参与形参按顺序一一对应传递数据;18/7019二、调用方式:按函数在程序中出现的位置来分,可以有以下三种函数调用方式:1、函数语句:由函数调用加上分号构成,在主调函数中可作为一个独立的语句stars(20);print_message();2、函数表达式:函数调用作为一个运算对象出现在表达式中,此时要求函数带回一个确定的值以参加表达式的运算c=max(a,b);3、函数参数:函数调用作为另一个函数的实参,其值作为一个实际参数传给被调函数的形参进行处理;此时也要求函数带回一个确定值m=max(a,max(b,c));printf(%d,max(a,b));19/7020三、说明:1、被调用的函数必须已经存在;2、使用库函数时,应在文件开头用#include命令将有关头文件包含进来;#includestdio.h#includemath.h#includestdlib.h3、若用户自己定义的函数在主调函数之后,则应在主调函数之前加原型说明(函数声明);4、如果函数类型是整型或字符型,可以省略类型说明,为了清晰起见,建议都作说明。20/70216.2.5函数的声明#includestdio.hvoidstars(intn);voidprint_message();main(){stars(20);print_message();stars(20);}voidstars(intn){……}voidprint_message(){……}#includestdio.hmain(){inta,b,c;intmax(intx,inty);scanf(%d%d,&a,&b);c=max(a,b);printf(max=%d\n,c);}intmax(intx,inty){return(xy?x:y);}21/7022一、函数声明的一般形式:函数类型函数名(类型名形式参数1,类型名形式参数2,……)包含参数和返回值类型的函数声明称为函数原型。函数类型函数名(类型名,类型名,……)假设有以下函数声明:floatfun(doublea,intb,floatc){……}①、floatfun(doublea,intb,floatc);②、floatfun(doublex,inty,floatz);③、floatfun(double,int,float);22/7023二、说明:1、老式的函数声明只写出函数名和函数类型,不包括参数类型和参数个数。④、floatfun();带来的问题是:编译器将不能对实参与形参是否匹配进行检查。2、如果函数的值是整型或字符型,可以不必进行声明,系统自动按整型声明。#includestdio.hmain(){inta,b,c;scanf(%d%d,&a,&b);c=max(a,b);printf(Max=%d\n,c);}intmax(intx,inty){intz;z=xy?x:y;return(z);}eg604.c23/70243、如果被调用函数出现在主调函数之前,可以不必进行声明。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/7025三、例: