《chap6函数与宏定义.ppt》由会员分享,可在线阅读,更多相关《chap6函数与宏定义.ppt(40页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第第6章章函数与宏定义函数与宏定义6.1函数概念函数概念C函数分函数分标准函数标准函数(库函数库函数)和和自定义函数自定义函数。所有函数都是平行的,相互独立不能嵌套定义,函数所有函数都是平行的,相互独立不能嵌套定义,函数间可以相互调用,但不能调用间可以相互调用,但不能调用main()函数。函数。6.1.1 函数的定义古典形式:古典形式:类型标识符类型标识符 函数名函数名(形式参数表形式参数表)形式参数说明;形式参数说明;函数体;函数体;现代简洁形式:现代简洁形式:类型标识符类型标识符函数名函数名(形参说明表形参说明表)函数体函数体;例:例:intmax(x,y)intx,y;/形式参数说明形式
2、参数说明/intz;/函数体中的说明部分函数体中的说明部分/z=xy?x:y;return(z);这两行可以写成一行:这两行可以写成一行:intmax(intx,inty)例:例:int max(int x,int y)int z;/函数体中的说明部分函数体中的说明部分 /z=xy?x:y;return(z);函数参数和函数的值函数参数和函数的值1形式参数和实际参数形式参数和实际参数例例从键盘输入两个数,输出其中较大的一个。从键盘输入两个数,输出其中较大的一个。main()int a,b,c;scanf(%d%d,&a,&b);c=max(a,b);/*a,b为实际参数为实际参数 */prin
3、tf(Max is%d,c);getch();max(int x,int y)/*x,y为形式参数为形式参数 */int z;z=xy?x:y;return(z);形形参参变变量量在在被被调调用用前前不不占占用用存存储储单单元元;在在被被调调用结束后,形参所占存储单元亦被释放。用结束后,形参所占存储单元亦被释放。实参可以是常量、变量或表达式。实参可以是常量、变量或表达式。必须指定形参类型,且应与实参的类型一致。必须指定形参类型,且应与实参的类型一致。实实参参对对形形参参的的数数据据传传递递是是“值值传传递递”。即即单单向向传递,不能逆传。传递,不能逆传。注意注意:函数的返回值是通过函数的返回值
4、是通过return语句获得的。语句获得的。return语句的后面可以有括号,也可以没有。如:语句的后面可以有括号,也可以没有。如:returnz;return(z);return语句的后面可以是变量,也可以是表达式。如:语句的后面可以是变量,也可以是表达式。如:return(xy?x:y);return语语句句返返回回值值的的类类型型应应与与该该函函数数的的类类型型一一致致。否否则以函数类型为准。则以函数类型为准。函数类型缺省时按整型处理。函数类型缺省时按整型处理。2函数的返回值函数的返回值若函数中没有若函数中没有return语句,则函数被调用后也会带回语句,则函数被调用后也会带回不确定的值不
5、确定的值。为了明确表示不需要函数返回值,可以用为了明确表示不需要函数返回值,可以用“void”定定义函数为义函数为“无类型无类型”。此时,不得使用。此时,不得使用a=f()之类的赋值之类的赋值语句。语句。凡不需要返回值的函数,一般均定义为凡不需要返回值的函数,一般均定义为“void”类型。类型。1函数调用的一般形式函数调用的一般形式函数名函数名(实参表实参表)说明:说明:对于无参函数,也不得省略一对小括号。对于无参函数,也不得省略一对小括号。“实参表实参表”中的参数之间用中的参数之间用逗号逗号分开。分开。实参与形参之间的个数及类型必须一一对应。实参与形参之间的个数及类型必须一一对应。函数的调用
6、函数的调用将函数调用作为一个语句。如:将函数调用作为一个语句。如:printf(“MSCpragramming”);gets(s);将被调用的函数写在表达式中。如:将被调用的函数写在表达式中。如:c=2 max(a,b);注意注意:被调用函数:被调用函数max必须有确定的返回值。必须有确定的返回值。将函数调用作为一个函数的实参。如:将函数调用作为一个函数的实参。如:m=max(max(a,b),c);2函数调用的方式函数调用的方式3对被调用函数的说明对被调用函数的说明在一个函数中调用另一个函数时:在一个函数中调用另一个函数时:如如果果被被调调函函数数为为库库函函数数,则则应应在在文文件件开开头
7、头用用“#include”命令声明相应的命令声明相应的“头文件头文件”。如:。如:#include“stdio.h”#include“math.h”如果被调函数为自定义函数且其定义在主调函数定义如果被调函数为自定义函数且其定义在主调函数定义之后,则应在主调函数中对该函数进行声明。其语句形之后,则应在主调函数中对该函数进行声明。其语句形式一般为:式一般为:类型标识符类型标识符被调函数名被调函数名(参数列表参数列表);如:如:floatadd(intx,inty);如如果果被被调调函函数数为为自自定定义义函函数数且且其其定定义义在在主主调调函函数数定定义义之前,则在主调函数中可不必声明。之前,则在
8、主调函数中可不必声明。如如果果已已在在所所有有函函数数定定义义之之前前已已作作了了函函数数声声明明,则则在在各各主调函数中可不必对所调用的函数再作声明。如:主调函数中可不必对所调用的函数再作声明。如:charletter();floatf();inti();main()/不不必必说说明明它它所所调调用用的的函函数数的的类类型型/1局部变量局部变量局局部部变变量量-在在一一个个函函数数内内部部定定义义的的变变量量,只只能能在在本本函数内使用和有效。函数内使用和有效。主主函函数数main中中定定义义的的变变量量,也也只只能能在在主主函函数数内内使使用用和有效。和有效。不同的函数中可以使用相同名字变
9、量,且互不干扰。不同的函数中可以使用相同名字变量,且互不干扰。形形式式参参数数也也是是局局部部变变量量,也也只只能能在在所所在在函函数数内内使使用用和和有效。有效。可可以以在在一一个个函函数数内内的的复复合合语语句句中中定定义义变变量量,且且这这些些变变量只在本复合语句中有效。量只在本复合语句中有效。这种复合语句也称为这种复合语句也称为“分程序分程序”或或“子模块子模块”。局部变量和全局变量局部变量和全局变量6.2 变量的作用域和存储类型变量的作用域和存储类型2全局变量全局变量全全局局变变量量(外外部部变变量量)-在在函函数数(包包括括main函函数数)外外定定义义的的变变量量。其其有有效效范
10、范围围为为从从定定义义变变量量的的位位置置开开始始到到本本源文件结束。源文件结束。在在文文件件开开头头定定义义的的外外部部变变量量才才可可在在整整个个文文件件范范围围内内使使用用,若若在在定定义义点点之之前前的的函函数数需需引引用用外外部部变变量量,则则可可用用关关键键字字“extern”作作“外部变量声明外部变量声明”。注意注意:外外部部变变量量的的定定义义只只能能有有一一次次,它它的的位位置置在在所所有有函函数数之之外外。而而同同一一程程序序中中的的外外部部变变量量声声明明可可以以有有多多次次,它它的的位位置置在在函函数数之之内内(哪哪个个函函数数要要用用就就在在哪哪个个函函数数中中说说明
11、明)。系系统统根根据据外外部部变变量量的的定定义义(而而不不是是根根据据外外部部变变量量的的说说明明)分分配配存存储储单单元元。对对外外部部变变量量的的初初始始化化只只能能在在“定定义义”时时进进行行,“extern”只只是是申申明明该该变变量量是是一个已在外部定义过的变量而已一个已在外部定义过的变量而已。如果在同一源文件中,外部变量与局部变量同名,则在局部变如果在同一源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用。量的作用范围内,外部变量不起作用。输出结果:输出结果:10,4,810,2,5例例#include stdio.hmain()int a=1,b=2,
12、c=3;a+;c+=b;int b=4,c;c=2*b;a+=c;printf(%d,%d,%dn,a,b,c);printf(%d,%d,%dn,a,b,c);getch();内内存存中中供供用用户户使使用用的的存存储储区区由由程程序序区区、静静态态存存储储区区和动态存储区组成。和动态存储区组成。变量的存储类型有四种:变量的存储类型有四种:自动的自动的(auto):内存的动态存储区:内存的动态存储区静态的静态的(static):静态存储区:静态存储区寄存器的寄存器的(register):寄存器:寄存器静静态态变变量量在在程程序序的的运运行行期期间间占占用用固固定定的的存存储储空空间间,直直到
13、到程序的终止而释放;程序的终止而释放;动动态态变变量量是是在在程程序序的的运运行行期期间间随随着着函函数数的的调调用用随随时时动动态态地占用和释放存储空间。地占用和释放存储空间。变量的存储类型变量的存储类型局部变量的存储方式局部变量的存储方式1)函函数数中中的的局局部部变变量量若若未未专专门门说说明明,这这类类局局部部变变量量称称为为自自动动变变量量,其其类类型型说说明明前前不不论论是是否否有有关关键键字字“auto”,都属于动态存储类别。都属于动态存储类别。2)若希望被调函数在结束后,其局部变量占用的存储空若希望被调函数在结束后,其局部变量占用的存储空间不释放,以便保留其变量的值,用于下次调
14、用该函数,间不释放,以便保留其变量的值,用于下次调用该函数,则用则用“static”说明为说明为“局部静态变量局部静态变量”。局部静态变量局部静态变量在在静静态态存存储储区区分分配配存存储储单单元元,在在程程序序的的整整个个运运行行期期间间都不释放。都不释放。在在编编译译时时只只赋赋初初值值一一次次,以以后后每每次次被被调调用用时时不不再再重重新新赋值而只保留前次被调用结束时的值。赋值而只保留前次被调用结束时的值。若若未未赋赋初初值值,则则在在编编译译时时自自动动赋赋初初值值0(数数值值型型)或或空空字符字符(字符字符型型)。虽然局部静态变量在函数被调用结束后其值仍然存在,虽然局部静态变量在函
15、数被调用结束后其值仍然存在,但其它函数是不能引用的。但其它函数是不能引用的。动态变量动态变量在动态存储区分配存储单元,函数调用结束后即释放。在动态存储区分配存储单元,函数调用结束后即释放。赋赋初初值值不不是是在在编编译译时时而而是是在在函函数数被被调调用用时时进进行行的的,函函数每次被调用时重新赋值。数每次被调用时重新赋值。若未赋初值,则其值是不确定的若未赋初值,则其值是不确定的例例打印打印1到到5的阶乘值。的阶乘值。intfac(intn)staticintf=1;/定义定义f为为int型静态变量型静态变量/f=f n;return(f);main()inti;for(i=1;i1 f(0)
16、=1,f(1)=1long fac(int n)long result;if(n=0|n=1)result=1;else result=n*fac(n-1);return result;main()int n;long f;printf(Please enter value of n:n);scanf(%d,&n);if(n(c+d)?(a+b):(c+d)如如果果第第一一行行写写成成:#defineMAX(x,y)xy?x:y则则这里的这里的t展开后为展开后为t=a+bc+d?a+b:c+d因为因为置换展开是用置换展开是用“表达式表达式”对等对等的置换的置换“形参表形参表”中的参数中的参数。
17、定义带参数的宏,可以实现一些简单的函数功能。定义带参数的宏,可以实现一些简单的函数功能。如:如:#defineMAX(x,y)(x)(y)?(x):(y)main()inta,b,c,t;t=MAX(a+b,c+d);6.5.2“文件包含文件包含”用用#include命令实现一个文件包含另一个文件。命令实现一个文件包含另一个文件。语句形式:语句形式:#include“文件名文件名”例例#include stdio.h#define N 2#define M N+1#define NUM (M+1)*M/2main()int i,n=0;for(i=1;i=NUM;i+)n+;printf(%2
18、d,n);getch();输出结果:输出结果:12345678一一个个include命命令令只只能能指指定定一一个个被被包包含含文文件件,如果要包含如果要包含n个文件,则要用个文件,则要用n个个include命令。命令。NUM被代换展开后为:被代换展开后为:(2+1+1)2+1/2#include命令中,文件名既可用双引命令中,文件名既可用双引“”号号(推荐),推荐),也可用尖括号也可用尖括号括起来。括起来。表示被包含在标准目录表示被包含在标准目录中中(include).“”表示被包含文件在指定目录中,表示被包含文件在指定目录中,若只有文件名不带路径,则在当前目录中,若找不若只有文件名不带路径
19、,则在当前目录中,若找不到,再到标准目录中找。到,再到标准目录中找。包含文件名可以是包含文件名可以是.c源文件或源文件或.头文件,如头文件,如#include#include“myhead.h”#include“D:myexammyfile.c”6.12条件编译条件编译语句形式:语句形式:1#ifdef宏名宏名程序段程序段1#else程序段程序段2#endif作用:如果宏名已定义,则编译作用:如果宏名已定义,则编译“程序段程序段1”,否则编,否则编译译“程序段程序段2”。所所谓谓“宏宏名名已已定定义义”是是无无论论“宏宏名名”定定义义为为什什么么内内容。容。条条件件编编译译的的作作用用:缩缩短
20、短编编译译时时间间,减减少少目目标标程程序序的的长长度。度。作用:如果宏名未定义,则编译作用:如果宏名未定义,则编译“程序段程序段1”,否则,否则编译编译“程序段程序段2”。3#if表达式表达式程序段程序段1#else程序段程序段2#endif作用:当作用:当“表达式表达式”值为非值为非0,则编译,则编译“程序段程序段1”,否则编译,否则编译“程序段程序段2”。2#ifndef宏名宏名程序段程序段1#else程序段程序段2#endif4#if表达式表达式1程序段程序段1#elif表达式表达式2程序段程序段2#else程序段程序段3#endif作用:当作用:当“表达式表达式1”值为非值为非0,则
21、编译,则编译“程序段程序段1”,否则判断否则判断”表达式表达式2”;当当“表达式表达式2”的值为真,则编译的值为真,则编译“程序段程序段2”,否则编译否则编译”程序段程序段3”。例例#define TED 10main()#ifdef TED printf(Hi,Tedn);#else printf(HI,Anyonen);#endif#ifndef PALPH printf(RAPLH not definedn);#endif getch();例main()#if MAX99 printf(compile for array greater than 99);#else printf(compile for small array);#endif getch();例例#define N 2#define M N+1#define NUM 2*M+1main()int i;for(i=1;i(y)?(x):(y)main()int a=5,b=2,c=3,d=3,t;t=MAX(a+b,c+d)*10;printf(%dn,t);/*t的值是多少?的值是多少?*/getch();作业:作业:6.41
限制150内