收藏 分享(赏)

c语言第6章 函数.ppt

上传人:fmgc7290 文档编号:8291357 上传时间:2019-06-18 格式:PPT 页数:43 大小:245.50KB
下载 相关 举报
c语言第6章 函数.ppt_第1页
第1页 / 共43页
c语言第6章 函数.ppt_第2页
第2页 / 共43页
c语言第6章 函数.ppt_第3页
第3页 / 共43页
c语言第6章 函数.ppt_第4页
第4页 / 共43页
c语言第6章 函数.ppt_第5页
第5页 / 共43页
点击查看更多>>
资源描述

1、1,1,第六章 函数,2,主要内容,3,6.1 函数的定义,无参函数 通常用来执行一些功能比较固定单一的语句。 例如:getchar( ),从形式上来说,函数分为两类:,有参函数 通常通过处理传递过来的参数,将函数值返回给调用处。 如:sqrt(4)、pow(2,3)、strlen(“hello”);,4,有参函数的定义形式:,6.1 函数的定义,例:float max( float a , float b ) return (ab)?a:b; ,类型标示符 函数名(形式参数列表) 函数体; ,函数头,5,6.1 函数的定义,例:void print_star( ) printf(“*”);

2、,类型名 函数名() 函数体; ,在定义函数时,也可以不指定形式参数列表,这样的函数就是无参数函数。其定义形式如下:,6,注意:函数的定义在程序中都是平行的,即不允许在一个函数的内部再定义另一个函数; 函数名是用户自定义标识符,当函数值为整型时类型名可省略(不推荐省略);当函数不需要向调用处返回值时,使用void类型名 形参表中的形参是用户自定义标识符,没有参数时,圆括号不能省略,此时函数为无参函数。,6.1 函数的定义,7,main( ) float x= max(3,4); ,6.2 参数传递,float max(float a,float b) return (ab)?a:b; ,调用m

3、ax时给出了实际参数。,定义max时使用了形式参数。,实际参数、形式参数,调用函数,被调函数,通过参数传递传入值,通过return返回值,注意:参数传递是单向值传递。,8,注意: (1)实参向形参的数据传递是单向的“值传递”。 实参和形参在内存中被分配到不同的单元,发生函数调用时,只是将实参的“值“传给形参,在函数中即使改变了形参的值也不会影响实参原来的值 (2)实参和形参的顺序应该一致且个数相等。 在调用函数时,如果实参顺序与函数定义的形参顺序不一致,形参可能无法接收到正确的值;如果实参与形参个数不一致,编译器会报错 (3)实参和形参的数据类型应尽量保持一致。,6.2 参数传递,9,6.2.

4、3 数组作参数,(1)把数组的元素作实参int a=1,2,3 fun1(a2)(2)把数组名作实参int a=1,2,3fun2(a),10,此时与普通变量作为实参进行参数传递没有区别,此时发生单向值传递。,6.2.3 数组元素作函数实参,例如: int a5=0,1,2,3,4; double y=sqrt(a2); int x=abs(a3); int z=max(a1,a3),11,例:计算5个学生成绩的平均分,学生成绩已在数组中存放。,6.2.3 数组名作函数实参,当用数组名作为函数实参时,函数形参会接收到此数组的首地址。这就意味着函数形参数组首地址等于实参数组首地址。 在函数中对形

5、参数组的操作直接作用于实参数组。,void main() int a3=4,5,6; f(a);/数组名作实参 ,void f(int b3) b0=8;b1=9; b2=10; ,12,void main() float s5=80,82,70,90,68; float a1=f1(s0,s1,s2,s3,s4);/数组元素作实参 float a2=f2(s,5); /数组名(数组首地址)作实参 ,float a1(float a,float b,float c,float d,float e) return (a+b+c+d+e)/5; ,float a2(float score,int

6、n) float result=0;int i;for (i=0;in;i+)result+=scorei;return result/n; ,在调用函数时需要传递多个实参,效率低、通用性差,在调用函数时只需传递两个实参,效率高、通用性强,13,6.3 函数的返回值,使用return语句,可以使函数向调用处返回一个值。,它有两个功能: (1)立即从所在的函数体中退出,返回到调用它的程序中去, (2)同时返回一个值给调用它的函数。,有两种常用方法可以让函数终止运行并返回到调用它的函数中去: (1)当执行到函数的最后一条语句后返回 (2)当执行到语句return时返回。,14,(1)如函数类型被定

7、义成void以外的任何一种类型,则函数内部必须出现return语句 (2)return语句中表达式的类型应与函数值类型一致。若不一致时,则以函数值的类型为准。,6.3 函数的返回值,注意:,int max(float x,float y) return xy?x:y; ,int main( ) float x=0.5,y=0.3,z;z=max(x,y);printf(“max=%f”,z);return 0; ,return语句返回float类型, 而max函数被定义为int类型, 返回值类型被强制转换为int,15,6.4 函数的调用,下列几种调用形式都是正确的: 函数以表达式语句的形式出

8、现。如:print_line( ); 函数出现在表达式中。v2=max(x,y)*10; 函数作其它函数的实参。num=max(max(max(a,b),c),d);,16,6.4.2 函数原型的提前声明,float max(float a,float b) return (ab)?a:b; void main() max(3.1,5.6); ,之前已经有了函数定义,函数和变量一样,也必须“先定义,后使用”。 下面定义的max函数就放在了主函数中调用语句之前,所以 主函数可以直接调用max。,17,6.4.2 函数原型的提前声明,int main() float a, b; scanf(“%f

9、 %f”, ,要调用在后面定义的函数,必须在调用函数之前提前声明此函数的原型,否则无法识别函数。原型可不写出形参名。,18,6.4.3 函数的嵌套调用,在一个函数定义的内部调用另外的函数。,C语言中所有函数的定义都是平行的,也就是说,不能在函数定义中再定义其它函数。 C语言允许在定义函数时调用其它函数,比如说函数a调用函数b,而函数b又调用函数c,这就是函数的嵌套调用。,19,6.4.3 函数的嵌套调用,int square(int a) return a*a; int pythagoras(int a,int b) return sqrt(square(a)+square(b); void

10、main() int x=pythagoras(3,4); ,20,C语言允许函数在定义中直接或间接地调用自己, 即函数的递归调用。,f( ) .f( );.,间接调用指在f1函数中调用了f2函数,但在f2函数中又调用了f1函数。,f1( ) .f2( );.,f2( ) .f1( );.,直接调用指在被调函数中直接调用本函数。,6.4.3 函数的递归调用,21,long factorial(int n) if(n1) return n*factorial(n-1); /*递归调用计算n!*/ else return 1; ,下面是一个直接调用的例子,求 n!,6.4.3 函数的递归调用,22

11、,int factorial(int n) if(n1) return n*factorial(n-1); else return 1; ,f(5),f(1),f(3),f(4),f(2),f(2),f(3),f(4),f(5),=1,=2*f(1)=2,=3*f(2)=6,=4*f(3)=24,=5*f(4)=120,n为5时:,factorial(int n) int i,fact=1;for(i=1;i=n;i+)fact*=i;return fact;,虽然递归调用可以使程序简洁、代码紧凑, 但内存消耗更大、效率较低。如可能的话,尽量用其它方式实现。,23,一般来说,递归需要有边界条件

12、、递归推进段和递归返回段。当边界条件不满足时,递归推进;当边界条件满足时,递归返回。上面例子中边界就是n=1在考虑使用递归算法编写程序时,应满足两点: 1)该问题能够被递归形式描述; 2)存在递归结束的边界条件,此时不能出现递归调用,否则永远无法返回。,6.4.3函数的递归调用,24,6.4.3 函数的递归调用,注意:尽量不要用递归方法实现算法。 编写递归函数时,必须在函数的某些地方使用if语句,强迫函数某次递归调用时返回。如不这样做,一但调用递归函数,将永远不会返回。,25,6.4.3 函数的调用,函数调用时需注意的一些常见问题:,有参函数在调用时,实参与形参个数必须相等,类型应尽量一致;如

13、 sqrt(4,3) sqrt(4),即便是在调用时无参函数,括号也不能省略。如 getchar( );,调用库函数时,应在程序头部用include宏命令把相关的头文件包含进来。如#include ,26,6.4 函数的调用,实参表达式求值的顺序是不确定的。,如(求3的2次方): n=3; pow(n,n-);,23,22,33,32,n=3; pow(n,n-1);,n=3; pow(n,-n);,32,27,void fun(int x) int y; if (x0) int x; ,6.5.1 程序块,成对的大括号及内部的语句组成了程序块。函数体、选择和循环结构中都要用大括号表示边界。

14、大括号内定义的变量,必须紧跟在左大括号后面,其作用范围是从定义处直到配对的右大括号之前。若多层大括号中出现重名变量,外层同名变量在内层中被屏蔽不起作用。,z作用域,x作用域,y作用域,28,main()int i,j;i=1; j=5;printf(“%d,%dn“,i,j);int i=8;i+; j+;printf(“%d,%dn“,i,j);i+; j+;printf(“%d,%dn“,i,j);,运行结果: 1,5 9,6 2,7,29,变量可以在程序中三个地方说明:函数的参数定义部分 形式参数 函数内部 局部变量 函数外部 全局变量(即大括号外的变量),6.5.2 局部变量 6.5.

15、3 全局变量,30,6.5.2 局部变量,在函数内定义的变量,其作用范围局限于此函数体内部,这种变量叫局部变量,函数的形参、在main函数中定义的变量也是局部变量。局部变量在函数被调用时由系统分配存储区,在不同的函数中同名的变量实际上在内存中占不同的单元,因此在不同的函数中可以定义相同名字的局部变量。,31,#include “stdio.h” void fun(int x, int y) int z=10; x+=10; y+=10; if(z) int z=20; printf(“x=%d y=%d z=%dn”, x, y, z); printf(“x=%d y=%d z=%dn”, x

16、, y, z); int main() int x=10, y=10, z=10; fun(x, y); printf(“x=%d y=%d z=%d”, x, y, z); return 0; ,程序的运行结果是: x=20 y=20 z=20 x=20 y=20 z=10 x=10 y=10 z=10,32,6.5.3 全局变量,在任何大括号外面定义的变量叫全局变量,其作用范围是从定义处直到文件末尾。由于全局变量作用范围很大,若在某个函数中修改了全局变量的值,在其它函数中读出的就是这个新值。,建议:用大写字母命名全局变量,便于区分局部变量。,33,#include “stdio.h” in

17、t x,y; void fun() int a=20, b=10; x=x+a+b; /x=8+20+10 y=y+a-b; /y=2+20-10 int main() int a=5, b=3; x=a+b; /x=8 y=a-b; /y=2 fun(); printf(“%d, %d”, x, y); /x=38, y=12 return 0; ,34,标准C语言支持四种变量存储类型。说明符如下: auto、static、extern、register。,6.6 变量的存储类型,35,6.6.1 自动变量,自动变量必须在函数中定义。当函数被调用,系统会自动创建自动变量并分配存储空间,当函数

18、调用结束时系统会自动销毁自动变量并释放存储空间。 如:auto int i; auto可以省去不写 如: int i; /等价于auto int ichar c; /等价于auto char cfloat f; /等价于auto float f,36,6.6.2 静态变量,在函数中定义的static变量与auto变量的区别: 在函数调用结束时: 自动变量会被自动销毁,而静态变量会被始终保留于内存直至整个程序结束后才被销毁。当再次调用该函数时, 将使用上次函数被调用时该静态变量被设置的值。,静态变量从被创建开始,直到程序结束才会被释放,也就是说静态变量在内存中一直存在直到程序结束。,37,int

19、 fun(int a) /* a是自动变量 */ int b=0; /* b是自动变量 */ static int c=3; /* c是静态变量 */ b+; c+; return (a+b+c); int main() int x=2, i; for (i=0; i3; i+) printf(“%dn”, fun(x); return 0; ,程序的运行结果是: 7 8 9,38,6.6.3 寄存器变量,使用“register”关键字声明变量,将建议编译器将变量的值存放在寄存器中。由于运算器访问寄存器的速度高于内存,一些频繁使用的变量放在寄存器中可以提高程序执行效率。,寄存器变量只能在函数中

20、定义。 定义一个整型寄存器变量可写成: register int a;,编译器会自动优化设置程序运行时变量的存放位置,用户不必做此声明,39,extern int x; /提升全局变量x作用范围至此 void main() x+; int x=8; void f1() x-; ,6.6.4.1 同一个文件中的外部变量,若在全局变量定义处之前想要访问这个变量,可以在相应的地方用“extern”关键字提前声明此变量,从而将在后面定义的全局变量作用范围扩展到前面来。,x原来的作用范围,x现在的作用范围,40,void num() extern int x,y; /*将全局变量x, y作用域扩展到此处

21、*/ int a=15,b=10; x=a-b; y=a+b; int x,y; /* 全局变量x, y */ int main() int a=7,b=5; x=a+b; /* x=7+5 */ y=a-b; /* y=7-5 */ num(); printf(“%d,%d”,x,y); return 0; ,程序的运行结果是: 5, 25,41,全局变量的作用范围还可以扩展至其它C程序文件,只需要在其它C程序文件中使用extern关键字说明一下即可。,6.6.4.2 同多个文件中声明的外部变量,int A; void printValue();/声明函数 int main() A=0; p

22、rintValue(); return 0; ,extern int A; /声明外部变量A void printValue() printf(“%d”, A); A+; ,prog1.c,prog2.c,42,若要禁止某个函数被其他C文件用extern关键字方式扩展过去访问,可以在定义此函数时用static关键字限制。 此函数就成了内部函数。,6.7.1 内部函数,extern void secret( ); extern void public( ); int main() secret( ); /错误public( ); /正确return 0; ,static void secret(

23、 ) /此函数只能本文件中访用 void public( ) /此函数其他文件也能访问 ,prog1.c,prog2.c,43,C程序一般都由多个源代码文件构成,函数可以被多个文件访问。只需在其他文件中将要访问的函数原型用extern关键字说明即可。,6.7.2 外部函数,extern void public1( ); extern void public2( ); int main() public1( ); /正确public2( ); /正确return 0; ,void public1( ) /此函数其他文件也能访问 void public2( ) /此函数其他文件也能访问 ,prog1.c,prog2.c,

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

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报