函数与编译预处理.ppt_第1页
函数与编译预处理.ppt_第2页
函数与编译预处理.ppt_第3页
函数与编译预处理.ppt_第4页
函数与编译预处理.ppt_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第六章 函数与预编译处理,教学目的要求: 1、掌握函数的一般概念和使用的时机 2、了解模块化程序设计的基本概念 3、掌握标准函数库的使用 4、掌握函数定义的形式、调用以及参数和参数传递 5、掌握编译预处理,尤其是宏定义 6、能灵活运用函数进行编程 重点难点: 1、模块化的概念及其设计原则 2、标准函数的使用方法 3、函数的概念、定义的形式、参数的传递以及实参、形参的区别 4、编译预处理中的带参宏定义 5、函数的嵌套调用,概 述,一件事情往往要实现多个功能,一个程序,多个函数,一个C程序可由一个主函数和若干个函数构成。,由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数

2、调用任意多次。,i,关于函数的几点说明,1、一个源程序文件由一个或者多个函数组成。 一个源程序文件是一个编译单位,而不是以函数为单位进行编译.,2、一个C程序由一个或者多个源文件组成。,3、从用户使用的角度看,函数有两种: 标准函数和用户自己定义的函数.,4、从函数的形式看,函数有两种: 无参函数和有参函数.,05.9-14以下关于函数的叙述中正确的是 A)每个函数都可以被其它函数调用(包括main函数) B)每个函数都可以被单独编译 C)每个函数都可以单独运行 D)在一个函数内部可以定义另一个函数,(B),print_star( ) printf( “* * * * * * * * * *

3、* * * * * * * *” ); ,* * * * * * * * * * * * * * * * * How do you do! * * * * * * * * * * * * * * * * *,print_message( ) printf( “nHow do you do ! n” ); ,main( ) printf_star( ); /* 调用printstar函数 */ print_message( ); /* 调用print_message函数 */ printf_star( ); /* printstar函数 */ ,2、 有参函数的定义形式 类型标识符 函数名(形式

4、参数表列) 声明部分 语句 ,函 数 定 义 的 形 式,1、 无参函数的定义形式 类型标识符 函数名() 声明部分 语句 ,int max( int x,int y ) int z ; z = x y ? x : y ; return( z ) ; ,函数类型 函数名(参数类型 参数名, , 参数类型 参数名),print_message( ) printf( “How do you do ! n” ); ,关 于 定 义 的 说 明,1、max为函数名,括号中有两个形式参数x和 y,均是整型。在调用时,主调函数把实参的值传递给被调用函数max中的形参x和y,这时x和y才获得相应的存储单元。

5、其本质是进行值的复制.,2、花括弧内是函数体,它包括声明部分和语句部分。在声明部分定义函数中所用的变量(局部变量)。,int max( int x , int y ) int z ; z = x y ? x : y ; return( z ) ; ,3、在语句部分中求解,return(z)的作用是将z的值作为整个函数的值带回到主调函数,return后面括号中的值z就是函数带回的值即函数返回值。,4、如果在定义函数时不指定函数类型,系统会隐含指定函数类型为int型。 因此上面定义的max函数左端的int可以省写。,函 数 参 数,形式参数 和 实际参数 在调用函数时,大多数情况下,主调函数和被调

6、用函数之间有数据传递关系。这就是前面提到的有参函数。,在定义函数时函数后面括弧中的变量名称为“形式参数”(简称“形参”),int max( int x , int y ),在主调函数中调用函数时,函数名后面括弧中的参数(可以是表达式)称为“实际参数”(简称“实参”), 如 c = max( a , b )。,main( ) int a,b,c; scanf(“%d,%d”, ,int max(int x,int y) int z; z=xy?x:y; return (z); ,a,b,c=max(a,b);,说 明,(5) 实参变量对形参变量的数据传递“值传递”,即单向传递,只由实参传给形参,

7、而不能由形参传回来给实参. 在内存中,实参单元与形参单元是不同单元。,swap(int x,int y) int t; t=x;x=y;y=t; ,main() int a=2,b=3; if(ab)swap(a,b); printf(“a=%d,b=%d”,a,b); ,函 数 的 返 回 值,通常,希望通过函数调用使主函数能得到 一个确定的值,这就是函数的返回值。例如, 例2中,max(2,3)的值是3。 赋值语句将这个函数值赋值给变量c。,函数的调用属于表达式的一种, 函数调用表达式的值即为函数的返回值,main( ) int a,b,c; scanf(“%d,%d”, ,int max

8、(int x,int y) int z; z=xy?x:y; return (z); ,说 明,下面对函数值作一些说明:,1、函数的返回值是通过函数中的return语句获得的。return 语句将被调用函数中的一个确定的值带回主调函数中去。,如果需要从被调用函数带回一个函数值(供主调函数使用), 被调用函数中必需包含return语句。如:例2,如果不需要从被调用函数带回函数值可以不要return语句,如:例1 或者有return语句,但没有具体返回值,即 return ; 语句。,两种情况:,说 明,(3)returen后面的值可以是一个表达式。 例如, max(int x,int y) re

9、turn(xy?x:y); ,注意: (1)一个函数中可以有一个以上的return语句(作为选择结构的各 个分支的内嵌语句; 不能出现顺序结构的多个return语句), 执行到哪一个return语句,哪一个语句起作用。,(2)return语后面的括弧可以不要,如return z;,如果出现多个 return 语句,且不是出现在选择结构的各个分 支中,则系统会自动执行第一个return语句,其它的不被执行,说 明,2、函数值的类型。 (1) 既然函数有返回值,这个值当然应属于某一个确定的类型, 应当在定义函数时指定函数值的类型。,(2) 凡不加类型说明的函数,一律自动按int处理。,(3) 在定

10、义函数时return语句中的表达式类型一般应该和函数说 明的类型一致。,3、如果被调用函数中没有return语句,不带回值。,但实际上,函数并不是不带回值,而只是不带回有用的值,带回的是一个不确定的值。, int a,b,c; a=printstar( ); b=print_message( ); c=printstar( ); printf(“%d,%d,%dn”,a,b,c); 上面的语句也是合法的,运行时除了可以得到和例1一样的结果外,还可以输出a、b、c的值。但是a、b、c的值没有实际意义。,说 明,4、为了明确表示“不带回值”,可以用void(空类型或无类型) 定义函数类型。,例如,

11、例1中的定义可以改为 void printstar( ) void print_message( ) ,这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用函数的返回值。,则下面的用法就是错误的: a=printstar(); b=print-message(); 编译时会给出出错信息。,05.9-30设函数fun的定义形式为 voidfun(charch,floatx) 则以下对函数fun的调用语句中,正确的是 A)fun(“abc”,3.0); B)t=fun(D,16.5); C)fun(65,2.8); D)fun(32,32); 06.4-46以下叙述中错误的是 A)C程序必须

12、由一个或一个以上的函数组成 B)函数调用可以作为一个独立的语句存在 C)若函数有返回值,必须通过return语句返回 D)函数形参的值也可以传回给对应的实参,等 考 实 例,(D),(D),函 数 的 调 用,函数调用的一般形式为 函数名(实参表列),如果是调用无参函数,则“实参表列”可以没有,但括弧不能省略,如果实参表列包含多个实参,则各参数间用逗号隔开。 实参与形参的个数应相等,类型应一致。 实参与形参按顺序对应,一 一传递数据。,函 数 调 用 的 方 式,按函数在程序中调用的位置,可以有以下三种函数调用方式: 1、函数语句:把函数调用作为一个语句。 如例1中的 printstar( )

13、; 这时不要求函数带回值,只要求函数完成一定的操作。,2、函数表达式 函数出现在一个表达式中,这种表达式称为函数表达式。 这时要求函数带回一个确定的值以参加表达式的运算。 例如: c=2*max(a,b);,3、函数参数 函数调用作为一个函数的实参。,例如:m=max(a,max(b,c); 又如:printf(“%d”,max(a,b);,实质上是函数表达式形式调用的一种,因为函数的参数本来就要求是表达式形式。,关于函数调用的几点说明,1、C程序的执行从main函数开始,调用其它函数后,流程回到main函数。,2、所有的函数都是平行的,即在定义函数时是互相独立的,一个函数并不从属于另一个函数

14、,即函数不能嵌套定义,函数间可以互相调用,但是不能调用main函数.,3、被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。,4、如果使用库函数,一般还应该在本文件开头用#include命令将调用有关库函数时所需用到的信息“包含”到本文件中来。,函 数 声 明,如果使用用户自己定义的函数,而且该函数与调用它的函数(即主调函数)在同一个文件中,一般还应该在主调函数中对被调用的函数作声明,即向编译系统声明将要调用此 函数,并将有关信息通知编译系统。,函数声明 int max ( int x , int y );,在函数声明中也可以不写形参名,而只写形参的类型。 如: int max

15、 ( int , int );,函数原型的一般形式为 1、函数类型 函数名(参数类型1,参数类型2),在C语言中,以上的函数声明称为函数原型。主要是利用它在程序的编译阶段对调用函数的合法性进行全面检查。,2、函数类型 函数名(参数类型1,参数名1, 参数类型2,参数名2),06.4-20若各选项中所用变量已正确定义,函数fun中通过return 语句返回一个函数值,以下选项中错误的程序是 A) main() x=fun(2,10); float fun(int a,int b) B) float fun(int a,int b) main() x=fun(i,j); C) float fun(

16、int,int); main() x=fun(2,10); float fun(int a,int b) D) main() float fun(int i,int j); x=fun(i,j); float fun(int a,int b),等 考 实 例,(A),05.9-12有以下程序 intsub(intn)return(n/10+n%10); main() intx,y; scanf(“%d”, 若运行时输入:1234,程序的输出结果是 。 06.4-33有以下程序 int fun1(double a)return a*=a; int fun2(double x,double y)

17、double a=0,b=0; a=fun1(x);b=fun1(y);return(int)(a+b); main() double w;w=fun2(1.1,2.0); 程序执行后变量w中的值是 A)5.21 B)5 C)5.0 D)0.0,等 考 实 例,10,(C),函 数 的 嵌 套 调 用,函数定义都是互相平行、独立的,不能嵌套定义. 可以做嵌套调用函数, 1、在调用一个函数的过程中,又调用另一个函数。 2、在定义一个函数的过程中,调用另一个函数,main( ) printstar( ); ,printstar( ) printf(“*”); printmessage( ) ; ,

18、printmessage( ) printf(“abcde”) ,函 数 的 递 归 调 用,在调用一个函数的过程中又直接或间接的调用该函数本身,称为函数的递归调用。 例如: int f(int x) int y,z, z=f(y); return(2*z); 递归调用分为: 直接调用和间接调用,函 数 的 递 归 调 用,直接调用,int f(int x) int y,z; z=f(y); return(2*z); ,int f1(int x) int y,z; z=f2(y); return(2*z); ,int f2(int x) int y,z; z=f1(y); return(2*z

19、); ,间接调用,程序中不应出现无终止的递归调用,而只应出现有限次数、有终止 的递归调用。可以用条件语句(if)控制。,函 数 的 递 归 调 用,例5 有5个人坐在一起, 问第5个人多少岁,他说比第4个人大2岁。 问第4个人岁数,他说比第3个人大2岁。 问第3个人,又说比第2个大2岁。 问第2个人,说比第1个人大2岁。 最后问第1个人,他说他10岁。请问第5人多大?,age(5)=age(4)+2; age(4)=age(3)+2; age(3)=age(2)+2; age(2)=age(1)+2; age(1)=10;,age(n)=10;(n= 1) age(n)=age(n-1)+2;

20、(n1),age(int n) int c; if(n= =1)c=10; else c=age(n-1)+2; return ( c ); ,函 数 的 递 归 调 用,回推,递推,main() int n , k ; scanf(“%d”, ,有如下递归过程,void print(int w) int i; if(w!=0) print(w-1); for(i=1;i=w;i+) printf(“%3d”,w); printf(“n”); 调用print(4)的结果是:,1 2 2 3 3 3 4 4 4 4,06.4-39有以下程序 int fun(int n) if(n=1)retur

21、n 1; else return(n+fun(n-1); main() int x; scanf(“d”, x=fun(x);printf(“dn”,x); 执行程序时,给变量X输入10,程序的输出结果是 A)55 B)54 C)65 D)45 06.4-10下面程序的运行结果是: 。 fun(int t,int n) int i,m; if(n=1) return t0; else if(n=2)m=fun(t,n-1); return m; main() int a=11,4,6,3,8,2,3,5,9,2; printf(“dn”,fun(a,10); ,等 考 实 例,(A),11,变

22、 量 的 作 用 范 围,在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的。这称为“局部变量”。 如: float f1( int a ) /*函数f1*/,说明: 1、主函数main中定义的变量也只在主函数中有效,而不因为在主函数中定义而在;主函数也不能使用其他函数中定义的变量。,2、不同函数中可以使用相同名字的变量,它们代表不同的对象, 互不干扰,它们在内存中占不同的单元 3、形式参数也是局部变量。 4、在一个函数内部,可以在复合语句中定义变量,这些变量只在 本复合语句中有效,这种复合语句也可称为“分程序”或“

23、程序块”。,float f1(int a) int b,c; char f2(int x,int y) int i,j; int e,f; main( ) int m,n; ,a、b、c有效,x、y、i、j有效,m、n有效,e 、 f有效,全局变量 在函数之外定义的变量称为外部变量(全局变量、全程变量), 全局变量可以为本文件中其他函数所共用。 它的有效范围为从定义变量的位置开始到本源文件结束。,变 量 的 作 用 范 围,说明: 如果在一个函数中改变了全局变量的值,就能影响到其他函数,相当于各个函数间有直接的传递通道。由于函数的调用只能带回一个返回值,因此有时可以利用全局变量增加与函数联系的

24、渠道,从函数得到一个以上的返回值。,局部变量 在函数内定义的变量是局部变量。 如:函数的形参,函数内部定义的变量,int p=1,q=5; float f1(int a) int b,c; char c1,c2; char f2(int x,int y) int i,j; main( ) int m,n; ,p、q有效,c1、c2有效,int a=3,b=5; /*a、b为全局变量*/ max(int a,int b) /*a、b为局部变量*/ int c; c=ab? a:b; return (c); main( ) int a=8; /*a为局部变量*/ printf(“%d”,max (

25、a,b); ,运行结果为:8,局部变量和全局变量同名时,全局变量在局部变量的作用范围内不起作用。,变 量 的 作 用 范 围(4),全局变量的作用范围是从定义变量的位置开始到本源文件截止.如果在定义点之前的函数想引用该外部变量,则应该在该函数中用关键字extern作外部变量声明.,int main(int x,int y) int z; z=xy?x:y; return z; main( ) extern int a,b; printf(“%d”,max(a,b); int a=13,b=-8;,变 量 的 存 储 类 别,从变量存在的时间(即生存期)角度来分,可以分为静态存储方式和动态存储方

26、式。 静态存储方式是指在程序运行其间分配固定的存储空间的方式; 动态存储方式是在程序运行其间根据需要进行动态的分配存储空间的方式。,一个变量的完整定义应包括数据类型和存储类型: 如 static int a; 变量的存储类型有四种: auto(自动) register(寄存器) static(静态) extern(外部) 存储类型确定了所说明对象在内存中的存储位置。,根据变量的存储类别,可以知道变量的作用域和生存期。 auto变量 函数的局部变量,如不专门声明static存储类别,都是自动分配存储空间的,即auto变量。数据存储在动态存储区中。函数中的形参和在函数中定义的变量(包括在复合语句中

27、定义的变量),都属此类,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。,变 量 的 存 储 类 别,用static声明局部变量 函数中的局部变量的值在函数调用结束后不消失而 保留原值,即其占用的存储单元没有释放,在下一次该函 数调用时,该变量已有值,就是上一次函数调用结束 时的值。,变 量 的 存 储 类 别(3),例staticau.c 静态变量和动态变量, 以及不同的函数中重名的局部变量,例: main() int i,sum; for(i=1;i=5;i+) sum=add(i); printf(“sum=%dn”,sum); add(int a) int s=0; s=s+a; return s; ,Static int s=0;,输出结果:5,输出结果:15,05.9-45有以下程序 inta=2; intf(intn) staticinta=3; intt=0; if(n%2)staticinta=4;t+=a+; elsestaticinta=5;t+=a+; returnt+a+; main() ints=a,i; for(i=0;i3;i+)s+=f(i); printf(“%dn”,s); 程序运行后的输出结果是 A)26 B)28 C)29 D)24,等 考 实 例,(C),预处理是指在进行词法扫描和语

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论