函数的定义 函数参数及函数返回值课件_第1页
函数的定义 函数参数及函数返回值课件_第2页
函数的定义 函数参数及函数返回值课件_第3页
函数的定义 函数参数及函数返回值课件_第4页
函数的定义 函数参数及函数返回值课件_第5页
已阅读5页,还剩104页未读 继续免费阅读

下载本文档

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

文档简介

1、第四章 函数 概述 函数的定义 函数参数及函数返回值 函数的调用 函数的嵌套与递归调用 变量存储类型、生存期和作用域 编译预处理模块化程序设计基本思想:将一个大的程序按功能分割成一些小模块,C语言中模块的功能用函数来实现。特点:各模块相对独立、功能单一、结构清晰、接口简单控制了程序设计的复杂性,提高了可读性缩短了程序开发周期,避免程序开发的重复劳动程序易于维护和功能扩充开发方法:自上向下,逐步分解,分而治之概 述 C语言是函数式语言 必须有且只能有一个名为main的主函数 C程序的执行总是从main函数开始,在main中结束 函数不能嵌套定义,可以嵌套调用概述:C程序结构C程序源程序文件1源程

2、序文件i源程序文件n预处理命令函数1函数n声明部分执行部分#includeint max(int x,int y) int max; if(xy) max=x; else max=y; return max;void main() int a,b,c; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“Max=%d”,c);概述:C程序结构【例】简单函数的例子:从键盘输入两个整数,求较大的整数。#includevoid main() int a,b,max; scanf(“%d,%d”,&a,&b); if(ab) max=a; else max=b; pri

3、ntf(“Max=%d”,max);运行结果:14,8Max=14主函数main()c=max(a,b);函数max()return max执行执行执行函数类型 函数名(形参表及类型) 数据描述(变量声明) 数据处理(执行语句)一般格式现代风格:例: 有参函数(现代风格) int max(int x,int y) int z; z=xy?x:y; return(z);/ return z; 例: 有参函数(现代风格) int max(int x, y) int z; z=xy?x:y; return(z); 例:空函数void input( ) 例:无参函数 void line( ) prin

4、tf(“*n”); 或 void line(void ) printf(“*n”); 函数的定义返回值类型,缺省为int型或char,无返回值void函数体注意:此处无;注意:此处括号不能省略函数类型 函数名(形参表)形参类型说明 变量声明 执行语句传统风格:例: 有参函数(传统风格) int max(x,y) int x,y; int z; z=xy?x:y; return(z); 函数的定义例: 有参函数(错误) int max(int x,y) int y; int z; z=xy?x:y; return(z); 格式不能混用!注意:VC环境不支持【例】求整数的最大公因子int gcd(

5、int u, int v) int tmp; while(v!=0) tmp=u%v; u=v; v=tmp; return u;函数的参数与传递main() int x=145,y=25,z; z=gcd(x,y); printf(“The GCD of %d and %d is %dn”,x,y,z); x=16; y=24; printf(“The GCD of %d and %d is %dn”,x,y,gcd(x,y); z=gcd(x,x+y); printf(“The GCD of %d and %d is %dn”,x,x+y,z);函数的参数与传递【例】求三个数的最大值/ E

6、xam.cpp#includeint max (int x,int y) /自定义有参函数,求两个数的较大值return xy?x:y;void line(void) /自定义无参函数,实现输出一行“*”号int i;for(i=1;i40;i+) printf(*);printf(n); void main(void)int a,b,c;int m;printf(请输入三个整数: );scanf(%d,%d,%d,&a,&b,&c);m=max(a,b); /有参数调用,实参分别是a,bm=max(c,m); /有参数调用,实参分别是c,mline(); /无参函数调用printf(%d,%

7、d和%d中的最大数为:%dn,a,b,c,m);line(); 说明: 实参必须有确定的值,可以是常量、变量或表达式 形参必须指定类型 形参与实参类型一致,个数相同 若形参与实参类型不一致,自动按形参类型转换-函数 调用转换 形参在函数被调用前不占内存,函数调用时为形参分配 内存,调用结束时,形参内存释放 实参对形参的数据传递是“值传递”,即单向传递。函数的参数与传递函数的参数与传递【例】实参与形参不匹配#includevoid test(float a,int b) printf(%f,%dn,a,b);void main( ) int x=3,y=2; float z=9.4; print

8、f(%d,%dn,x,y); test( );/无实参调用,编译错误 test(x,y);/实参的类型不匹配,会自动转换,但容易引起错误 test(z,y,x);/实参个数不匹配,编译错误 test(float)x,y);/正确调用参数传递方式:值传递方式:函数调用时,为形参分配单元,并将实参的值复制到形参内存中;调用结束,形参单元被释放,实参单元仍保留并维持原值特点:形参与实参占用不同的内存单元实参向形参传递次序依不同系统而定单向传递,即形参值的改变不会影响实参的值函数的参数与传递711x:y:调用前:调用结束:711x:y:【例】单向值传递 #include void swap(int a

9、,int b) int t; t=a; a=b; b=t; void main() int x=7,y=11; printf(x=%d,y=%dn,x,y); printf(swapped:n); swap(x,y); printf(x=%d,y=%dn,x,y);调用:711a:b:711x:y:swap:711x:y:117a:b:t函数的参数与传递运行结果:x=7, y=11swapped:x=7, y=11函数返回值说明:函数中可有多个return语句,执行哪个return,哪个语句 起作用;若无return语句,遇时,自动返回主调函数若函数类型与return语句中表达式值的类型不一致

10、,按 前者为准,自动转换-函数调用转换无返回值函数:void函数返回值【例】存在多个return语句#include void main() int max(int x,int y); /函数声明 int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(Max is %dn,c);int max(int x, int y) if(xy) return x; else return y;说明:xy:返回xxy:返回y函数调用:在一个函数中引用另一个函数说明:主函数main()只能被系统调用。调用无参函数时,实参表可以没有,但括号不能省略。如line(

11、)实参与形参个数相等,类型匹配,按顺序一一对应各参数用逗号分隔,实参向形参传递顺序,因系统而定(VC 自左向右)函数的调用函数名(实参表);void func(int a;int b) /*函数定义*/void main() int a=2,b=1; func(a,b); /*函数调用*/函数的调用【例】实参传值的顺序#includeint f(int a,int b) int c; if(ab) c=1; else if(a=b) c=0; else c=-1; return c;void main() int i=2,p; p=f(i,+i); printf(“%dn”,p);运行结果:T

12、urbo C环境运行结果:VC环境-f(3,3)f(2,3)语句调用: 例 : line(); printf(“Hello,World!n”);表达式调用: 例: m=max(a,b)*2;函数参数调用: 例: printf(“%d”,max(a,b); m=max(a,max(b,c);函数的调用方式对被调用函数要求:必须是已存在的函数使用库函数,用#include将所需的信息包含到本文件中。 #include 用户自定义函数: 若函数位置在主调函数后面,必须在主调函数中对该函数进行声明。主调函数和被调函数的相对位置被调用函数声明与函数原型 函数声明形式:作用:告诉编译系统函数类型、参数个数

13、及类型,以便检验函数定义与函数声明不同。函数声明位置:程序的数据说明部分(函数内或外)若被调用函数定义出现在主调函数之前,可不作函数声明。有些系统要求函数说明指出函数返回值类型和形参类型,并且对void和int型函数也要进行函数说明。函数类型 函数名(类型1,类型2);或函数类型 函数名(类型 参数1,类型 参数2);必须有分号可以只写明类型main() int max(int,int); /函数声明int max(int x , int y) /函数定义#include long sum(int a, int b); long factorial(int n);void main() int

14、 n1,n2; long a; scanf(%d,%d,&n1,&n2); a=sum(n1,n2); printf(a=%1d,a);long sum(int a,int b) long c1,c2; c1=factorial(a); c2=factorial(b); return(c1+c2); long factorial(int n) long rtn=1; int i; for(i=1;i=n;i+) rtn*=i; return(rtn); long sum(int a, int b);long factorial(int n);函数调用函数调用被调用函数声明与函数原型函数声明函数

15、定义若被调函数的定义出现在主调函数之后,必须在主调函数或文件中对被调函数进行声明。【例】函数调用示例 计算:A(x,y)=#include#includedouble fun(double f) double f2=f*f+sqrt(1+2*f+3*f*f); return (sqrt(f2);main () int x,y; double f1,fun(double ); scanf(“%d,%d”,&x,&y); f1=x*x/fun(exp(x-y); printf(A(x,y)=%fn,f1);被调用函数声明与函数原型嵌套调用C规定:函数定义不可嵌套,但可以嵌套调用函数函数的嵌套调用m

16、ain( )调用函数a结束a函数b函数调用函数b两层嵌套示例错误,函数的嵌套定义main() int max(int x,int y) return(xy?x:y); 递归调用:函数直接或间接的调用自身。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 t) int a,c; c=f1(a); . return(3+c);函数的递归调用f( )调f调f2调f1f1( )f2( )说明: C编译系统对递归函数的自调用次数没有限制。 每调用函数一次

17、,在内存堆栈区分配空间,用于存放函数 变量、返回值等信息,所以递归次数过多,可能引起堆 栈溢出。 程序中应避免无终止的递归调用(有递归出口)函数的递归调用【例】有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人的岁数,他说比第3个人大2岁。而第3个人,又比第2个人大2岁,第2个人又比第1个人大2岁。已知第1个人10岁。求第5个人的年龄。递推回归递归结束的条件函数的递归调用#includeint age(int n) int c; if(n=1) c=10; else c=age(n-1)+2; return c;void main() printf(“The fifth pe

18、ople is %d years old.”,age(5);运行结果:The fifth people is 18 years old.递归结束条件if递归调用(4次)函数调用main()递 推回 归c=age(5)age(5)c=age(4)+2age(4)c=age(3)+2age(3)c=age(2)+2age(2)c=age(1)+2结束结束结束结束结束0函数的递归调用age(1)c=10结束1234#include int fac(int n) int f; if(n0) printf(n0,data error!); else if(n=0|n=1) f=1; else f=fac

19、(n-1)*n; return(f);main() int n, y; printf(Input a integer number:); scanf(%d,&n); y=fac(n); printf(%d! =%10d,n,y);【例】求n的阶乘函数的递归调用运行结果:Input a integer number:88!= 40320main() int i,s=1; for(i=1;i=10;i+) s=s*i;函数的递归调用【例】汉诺塔问题 设计一个移动盘子的程序,使塔A上的所有盘子借助塔B移到塔C上。要求: 一次只能移动一个盘子; 任何时候不能把大盘子放在比它小的盘子上面。ABCABC初

20、始结果(1)从A移动1n-1号圆盘至B,C作辅助;(递归调用)分析此问题可归之于三个子问题(2)从A移动n号圆盘至C;(一次搬运)(3)从B移动1n-1号圆盘至C,A作辅助。(递归调用)ABC1n-1nABC(1)n1n-1ABC(2)n1n-1ABC(3)n1n-1函数的递归调用分析如下:首先,分析如何将A柱上3个盘子移到C柱上的过程;1)将A柱上2个盘子移到B柱上(借助C);2)将A柱上1个盘子移到C柱上;3)将B柱上2个盘子移到C柱上(借助A).其中2)可以直接实现。其中1)可用递归方法分解:1.1将A上1个盘子从A移到C;1.2将A上1个盘子从A移到B;1.3将C上1个盘子从C移到B。

21、其中3)分解为3.1将B上1盘子从B移到A上;3.2将B上1盘子从B移到C上;3.3将A上1盘子从A移到C上。函数的递归调用函数的递归调用【例】汉诺塔问题#includevoid hanio(int num,char A,char B,char C) if(num0) hanio(num-1,A,C,B); printf(“移动第%d个盘:从%c柱到%c柱n”,num,A,C); hanio(num-1,B,A,C);void main() int num; printf(“please input the number of plate(0):”); scanf(“%d”,&num); ha

22、nio(num,A,B,C);运行结果:Please input the number of plate:3移动第1个盘:从A柱到C柱移动第2个盘:从A柱到B柱移动第1个盘:从C柱到B柱移动第3个盘:从A柱到C柱移动第1个盘:从B柱到A柱移动第2个盘:从B柱到C柱移动第1个盘:从A柱到C柱函数的递归调用读程序,写结果#includevoid f(int x) if(x%3!=0) f(x/3); printf(%dt,x); main( ) f(5); printf(end); 运行结果:0 1 5 endf(5)f(1)f(1)f(0)f(0)递推结束打印 x打印 x打印 xmain()f(

23、5)打印”end”变量存储类型、生存期和作用域变量的数据类型规定了变量的存储空间大小和取值范围; (已介绍)变量的存储类型规定了变量的生存期和作用域。变量的存储类型有4个,分别是自动型、寄存器型、外部型和静态型,其说明符分别是auto、register、extern和static。 变量定义格式: 存储类型 数据类型 变量表;如: int sum; auto int a,b,c; register int i; static float x,y; 存储类型:变量存储类型、生存期和作用域生存期,就是变量存活的周期。 一是变量从程序开始定义就被分配内存(即产生),直 到程序运行结束内存释放,这种变

24、量称为静态变量;二是变量带有临时性,随调用的模块(如文件、函数或 复合语句)分配内存单元,模块调用结束,释放内存, 这种变量称为动态变量。作用域,就是某个变量在其生命期内,程序模块是否可使用该变量。一种变量在从定义点开始或整个源程序都可有效,称为全局变量;另一种变量只能在所定义的模块内部有效,称为局部变量。局部变量-内部变量定义:在模块内定义,只在本模块内有效说明:main中定义的变量只在main中有效,各函数不能使用其他函数中定义的变量。不同函数中的同名局部变量,占不同内存单元形参属于局部变量复合语句中定义的局部变量只在该复合语句中有效局部变量可用存储类型:auto、register、sta

25、tic (默认为auto)float f1(int a) int b,c; .char f2(int x,int y) int i,j; main() int m,n; .a,b,c有效x,y,i,j有效m,n有效/定义在复合语句中的变量#includemain() int x=1,y=2; /复合语句中定义 int x=10; x=x+10; printf(“x=%d,”,x); printf(“y=%d,”,y); x=x+9; printf(“x=%dn”,x);/不同函数中的同名变量sub() int a,b; a=6; b=7; printf(sub:a=%d,b=%dn,a,b);

26、main() int a,b; a=3; b=4; printf(main:a=%d,b=%dn,a,b); sub(); printf(main:a=%d,b=%dn,a,b);运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4变量的作用域-局部变量 复合语句中x的作用域 sub中的a、b作用域 main中的a、b作用域 main中x、y的作用域运行结果:x=20,y=2,x=10全局变量-外部变量定义:在函数外定义,可为本文件中所有函数共用有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件说明:外部变量可用存储类型:缺省 或 sta

27、tic若外部变量与局部变量同名,则外部变量被屏蔽变量的作用域-全局变量/全局变量的作用域 int p=1,q=5; /*全局变量*/float f1(int a) int b,c; char c1,c2; /*全局变量*/char f2(int x, int y) int i,j; void main() int m,n;c1,c2的作用范围p,q的作用范围/外部变量被屏蔽#include int a=3,b=5;max(int a, int b) int c; c=ab?a:b; return(c);main() int a=8; /与外部变量同名 printf(max=%d,max(a,b

28、);运行结果:max=8变量的作用域-全局变量变量的作用域-全局变量【例】外部变量的使用#includeint x;void add(void) x=x+5; printf(“add_x=%dn”,x);void sub(void) x=x-2; printf(“sub_x=%dn”,x);void main() add(); sub(); printf(“外部_x=%dn”,x);未初始化的外部变量,系统赋初值为0运行结果: add_x=5 sub_x=3 外部_x=3变量的作用域-全局变量【例】外部变量的使用#includeint x1=30 , x2=40;sub(int x , int

29、 y) x1=x; x=y; y=x1;void main() int x3=10 , x4=20; sub(x3,x4); sub(x2,x1); printf(“%d,%d,%d,%d”,x3,x4,x1,x2);运行结果: 10 ,20 ,40 ,40变量的作用域-全局变量应尽量少使用全局变量: 全局变量在程序全部执行过程中占用存储单元 降低了函数的通用性、可靠性,可移植性 降低程序清晰性,且容易出错静态变量与动态变量存储方式静态存储:程序运行期间分配固定存储空间动态存储:程序运行期间根据需要动态分配存储空间生存期静态变量:从程序开始执行到程序结束动态变量:从包含该变量定义的模块开始执行

30、至模块执行结束全局变量、静态变量外部变量形参变量局部变量程序区静态存储区动态存储区动态变量 auto变量 数据:函数中的形参和函数中定义的变量。 动态存储方式:调用函数时分配空间,函数执 行结束释放。 声明: int f(int a) auto int b,c=3; 等价于:int b,c=3; (auto可省略)动态变量 register变量作用:减少频繁使用变量的存取开销。/输出1!到n!的值#include void main() long fac(long); long i,n; scanf(“%ld”,&n); for(i=1;i=n;i+) printf(“%ld!=%ldn“,i

31、,fac(i);long fac(long n) register long i,f=1; for(i=1;i=n;i+) f=f*i; return(f);运行结果:51!12!23!64!245!120动态变量说明: 只有局部自动变量和形式参数可以作为寄存器变量 寄存器变量数目有限 局部静态变量不能定义为寄存器变量 错误:register static int a,b,c; 一般优化的编译系统能识别使用频繁的变量,并将 其放入寄存器,不需要程序设计者指定。静态变量 static变量 静态存储方式:编译时分配空间,整个程序运行过程中 有效。 静态局部变量: 限于本函数(或复合语句中)使用,函

32、数调用后仍可保留空间,其值可用于下次调用时继续使用。(其值具有可继承性) 静态外部变量: 外部变量只限于本文件使用。静态变量#includevoid main() void increment(void); increment(); increment(); increment();void increment(void) int x=0; /auto x+; printf(“%dn”,x); #includevoid main() void increment(void); increment(); increment(); increment();void increment(void)

33、static int x=0; /static x+; printf(“%dn”,x); 运行结果: 1 1 1运行结果: 1 2 3【例】static声明为局部变量【例】static声明为局部变量#includevoid main() int f(int); /函数声明 int a=2,i; for(i=0;i3;i+) printf(“%dt”, f(a);int f(int a) auto int b=0; /局部变量 static int c=3; /静态局部变量 b=b+1; c=c+1; return(a+b+c);运行结果:7 8 9调用次数调用初值调用结束值bcbca+b+c1

34、03147204158305169注意: 静态局部变量:局限于变量所在 的模块; 每次函数调用时,其初值是上次 调用结束时的值;静态变量说明: 静态局部变量属于静态存储类别,其存储单元在整个程序 运行期间不释放。自动变量属于动态存储类别。 静态局部变量在编译时赋初值,即只赋初值一次。每次函 数调用时不再重新赋初值,而是保留上次函数调用结束时 的值。自动变量每次执行函数调用时,重新赋初值。 静态局部变量未赋初值时,编译时自动赋初值0或空字符 。自动变量则是不确定的值。 静态局部变量只限于定义它的函数使用,其它函数不能引 用。静态变量【例】static声明为外部变量/*File1.c*/stati

35、c int a;void main() /*File2.c*/extern int a;void fun(int n) a=a*n; 错误:a只能用于本文件(file1.c)中静态变量静态变量static unsigned int r; /static外部变量random(void) r=(r*123+59)%65535; return (r);/*产生r的初值*/unsigned radom_start(unsigned int seed) r=seed;【例】产生一个随机数序列main() int i,n; printf(“please enter the seed:”); scanf(“

36、%d”,&n); random_start(n); for(i=1;i10;i+) printf(“%u”,random();外部变量 用extern声明外部变量 非变量定义,而是用于扩展外部变量的作用域 应用:在一个文件内声明外部变量在多个文件的程序中声明外部变量 声明方式:extern 数据类型 变量名; 如:extern a; 或 extern int a;c1,c2的作用范围p,q的作用范围extern char c1,c2;extern char c1,c2; 外部变量定义与声明(extern)扩展后的c1,c2的作用范围扩展后的c1,c2的作用范围int p=1,q=5; floa

37、t f1(int a) int b,c; .int f3().char c1,c2; char f2(int x,int y) int i,j; main() int m,n; .#includeint max(int x, int y) int z; z=xy?x:y; return(z);main() extern int a,b; /声明外部变量 printf(max=%d,max(a,b);int a=13,b=-8; /定义外部变量运行结果:max=13#includeextern int a,b;int max() int z; z=ab?a:b; return(z);main()

38、 printf(max=%d,max();int a=13,b=-8;【例】外部变量定义与说明外部变量定义与声明(extern)注意: 若在外部变量定义点之前引用该变量,必须在引用前用 extern对该变量作出声明。 声明后,作用域从“声明”处起有效。外部变量定义与声明(extern)【例】用extern将外部变量的作用域扩展到其他文件/file1.c#include void main() int power(int); int b=3,c,d,m; printf(“enter the number a and its power m:n”); scanf(“%d,%d”,&A,&m); c

39、=A*b; printf(“%d*%d=%dn”,A,b,c); d=power(m); printf(“%d*%d=%dn”,A,m,d);/file1.c#include #includeextern int a; /扩展file2中的a的作用域void main() int power(int); /函数声明 int b=3,c,d,m; printf(“enter the number a and its power m:n”); scanf(“%d,%d”,&a,&m); c=a*b; printf(“%d*%d=%dn”,a,b,c); d=power(m); printf(“%d

40、*%d=%dn”,a,m,d);/file2.cint a; /外部变量定义int power( int n) int i,y=1; for(i=1;i=n;i+) y*=a; return(y);运行结果:enter the number a and its power m5,35*3=155*3=125外部变量定义与声明(extern)【例6-18】外部变量的副作用示例。/Exam6-18.cpp#includeint i;/定义外部变量i/-void output(void)for(i=1;i5;i+) putchar(*);/-void main(void)for(i=1;i6;i+)

41、 output();/= 运行结果:*【例】外部变量的副作用示例。/Exam.cpp#includeint i;/定义外部变量i/-void output(void)for(i=1;i5;i+) putchar(*);/-void main(void)for(i=1;i6;i+) output();/= 运行结果:*若此处i6改为i7,程序结果会是怎样?变量存储类型【例】静态外部变量与外部变量的区别示例。/file1.cpp#include/-int x=2;/定义外部变量xstatic int y=3;/定义静态外部变量y/-void func( )x+;y+;printf(“x=%d,y=

42、%dn,x,y);/=/file2.cpp#include/-extern int x;/扩展文件file1中的外部变量x的作用域int y;/外部变量/-void main() void func(); /函数声明func(); / 函数调用printf(“x=%d,y=%dn,x,y);/=运行结果:x=3,y=4x=3,y=0注意: 静态外部变量只能在定义的文件中使用,具有局部可见性。 外部变量可以被其他文件使用,具有全局性。#include int i=1;main() static int a; register int b=-10; int c=0; void other(); p

43、rintf(-MAIN-n); printf(i:%d a:%d b:%d c:%dn,i,a,b,c); c=c+8; other(); printf(-MAIN-n); printf(i:%d a:%d b:%d c:%dn,i,a,b,c); i=i+10; other();void other() static int a=2; static int b; int c=10; a=a+2; i=i+32; c=c+5; printf(-OTHER-n); printf(i:%d a:%d b:%d c:%dn,i,a,b,c); b=a;运行结果:-Main-i:1 a:0 b:-10

44、 c:0 -Other-i:33 a:4 b:0 c:15 -Main-i:33 a:0 b:-10 c:8-Other-i:75 a:6 b:4 c:15变量存储类型变量存储类型 外部变量的作用域可以在不同的函数中多次扩展,但 外部变量的定义在一个源程序中只能定义一次,可以 定义时进行初始化 外部变量和局部变量在同一个模块中有效时,同名的 外部变量被屏蔽 静态外部变量和外部变量定义时如果没有赋初值,数 值型变量默认为0,字符型为空字符静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区寄存器

45、局部变量全局变量作用域定义变量的函数或复合语句内本文件其它文件register局部staticauto外部staticextern存储类别变量存储类型小结变量存储类型小结#includeint fun(int x,int y) static int m=0,i=2; i+=m+1; m=i+x+y; return m; void main() int j=4,m=1,k; k=fun(j,m); printf(%d,k); k=fun(j,m); printf(%dn,k); 读程序,写结果结果:8,17函数的存储类别内部函数(又称为静态函数) :只能被本文件中的其它函数调用,而不能被同一源程

46、序中其它文件中的函数调用,这种函数称为内部函数。外部函数:在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数:说明此函数可以被同源文件中的其它文件调用。static 函数类型 函数名(形参列表) 函数体 static的含义不是指存储方式,而是限定函数的作用域于本文件中。 extern 函数类型 函数名(形参列表) 函数体 编译预处理 宏定义 文件包含 条件编译第八章编译预处理命令作用:不是C语言的组成部分,对源程序编译之前做一些预处理,生成扩展C源程序。种类宏定义 #define文件包含 #include条件编译 #if-#else-#endif

47、 等格式:“#”开头(区别于其它C语句)单独占书写行语句尾不加分号功能:一个源文件可将另一个源文件的内容全部包含进来一般形式:#include “文件名” 或 #include 处理过程:预编译时,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作为一个源文件编译。#include “file2.c”file1.cfile2.cfile1.cfile2.cABBAB 直接按标准目录搜索“” 先在当前目录搜索,再搜索标准目录,可指定路径文件包含 一次只能包含一个文件 被包含的文件一定是文 本文件,不能是执行程 序或目标程序源文件(*.c)头文件(*.h)宏定义数据结构定义函数说明等文件包

48、含可嵌套#include “file2.c”file1.cAfile3.cC#include “file3.c”file2.c Bfile1.cAfile3.cfile2.c文件包含/* powers.h */#define sqr(x) (x)*(x)#define cube(x) (x)*(x)*(x)#define quad(x) (x)*(x)*(x)*(x)/*Exam.c*/#include /一个#include只包含一个文件#include d:c_propowers.h#define MAX_POWER 10void main() int n; printf(numbert

49、exp2t exp3t exp4n); for(n=1;n=MAX_POWER;n+) printf(%2dt %3dt %4dt %5dn,n,sqr(n),cube(n),quad(n);文件包含#define sqr(x) (x)*(x)#define cube(x) (x)*(x)*(x)#define quad(x) (x)*(x)*(x)*(x)不带参数宏定义一般形式:#define 标识符 字符串功能:预处理程序中用字符串(或宏体)代替标识符(或宏名),此过程称为“宏展开”。宏定义【例】不带参数的宏定义#include#define PI 3.14159void main() d

50、ouble s,r; printf(“Input radius:”); scanf(“%f”,&r); s=PI*r*r; printf(“The circles area is %10.4f”,s);运行结果:Input radius:4The circles area is 50.26543.14159*r*r,宏展开是任意类型数据 #define A 3.6#define A “CHINA”宏定义说明: 宏名一般用大写形式 使用宏定义,可以减少重复书写某字符串的工作量 用宏体替换宏名,只作简单的替换,不作任何语法检查 如:#define PI 3.14l59 宏定义,行末不加分号 #de

51、fine一般用在函数的外面,其有效范围为定义命令之后 到本源文件结束。也可以用#undef命令终止宏定义的作用域。 如: #define G 9.8 void main() #undef G f1()G的有效范围宏定义 宏定义可以嵌套,但不能递归。如:#define MAX MAX+10 ()如:#define MIN 10 #define MAX MIN*10 ()【例】 #include #define MIN 10 #define MAX MIN*10 void main() printf(“min=%d,max=%d”,MIN,MAX); 运行结果:min=10,max=100【修改】

52、#define MIN 5+5#define MAX MIN*10输出:min=10,max=55宏展开:5+5*10注意:宏名出现在引号中,不作宏替换。如:”MIN”如: #define S(a,b) a*b area=S(3,2);宏展开:area=3*2;带参数的宏定义: 一般形式:#define 宏名(参数) 字符串宏定义3*2#include#define PI 3.14159#define S(r) PI*r*rvoid main() float a ,area; a=3.6; area=S(a); printf(“r=%f,area=%fn”,a,area);宏展开:形参用实参替

53、换,其它字符保留宏展开:3.14159*3.6*3.6宏定义说明: 带参数宏的展开只是将宏名括号内的实参字符串代替宏定 义中的形参。宏名与带参数的括号间不应加空格,否则空格后的字符串都 作为宏体的一部分。如: #define S (r) PI*r*r /宏名为S,字符串为(r) PI*r*r 遇area=S(a); 展开为 (r) PI*r*r(a);如:#define POWER(x) x*x x=4; y=6; z=POWER(x+y);宏展开:z=x+y*x+y;注意:实参是表达式时,宏定义中要用括号把参数括起来。如:#define POWER(x) (x)*(x)宏展开:z=(x+y)

54、*(x+y);#define MAX(x,y) (x)(y)?(x):(y) .main() int a,b,c,d,t; . t=MAX(a+b,c+d); 宏展开:int max(int x,int y) return(xy?x:y);main() int a,b,c,d,t; . t=max(a+b,c+d); 宏定义与函数t=(a+b)(c+d)?(a+b):(c+d);宏定义与函数 带参宏 函数处理时间 编译前 程序运行时参数类型无类型说明(无类型匹配问题)指明形参类型处理过程不分配内存,仅简单字符替换,不计算分配内存先求实参值,再传给形参程序长度变长不变宏定义 【例】用宏定义编制打

55、印不同半径圆的周长、面积及球的体积的程序。#define PI 3.14159#define SQUARE(x) (x)*(x)#define CUB(x) (x)*(x)*(x)double area(double r) return(PI*SQUARE(r); double cirfer(double r) return(2.0*PI*r); double vol(double r) return(4.0/3.0*PI*CUB(r); main() double r=2.0; printf(“r=%f:%f %f %fn”,r,area(r),cirfer(r),vol(r);宏定义 【例

56、】定义一个带参数的宏,使两个参数的值互换,并编一个程序,输入两个整数作为使用宏时的参数,输出已经交换的两个值。#define SWAP(a,b) t=b;b=a;a=t;main() int a,b,t; printf(“请输入两个整数:”); scanf(“%d,%d”,&a,&b); printf(“n原来得数据为:a=%d,b=%dn”,a,b); SWAP(a,b); printf(“交换结果为:a=%d,b=&dn”,a,b);运行结果:请输入两个整数:87,96原来的数据为:a=87,b=96交换结果为:a=96,b=87条件编译条件编译:根据条件选择被编译的源程序行。 使用宏定义

57、的标识符作为编译条件 使用常量表达式的值作为编译条件 #ifdef形式:格式1#ifdef 标识符 程序段1 #else 程序段2 #endif 作用:当所指定的标识符已经被#define 命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。条件编译# ifdef 标识符 程序段1 #endif 格式2:作用:当所指定的标识符已经被#define 命令定义过,则在程序编译阶段只编译程序段1,# ifndef 标识符 程序段1 # else 程序段2 # endif 格式3:作用:当所指定的标识符未被#define 命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。条件编译

58、【例】:用于程序调试#include void main() #ifdef FLAG printf(“FLAG已被定义”); #else printf(“FLAG未被定义”); #endif#define FLAG 1运行结果:FLAG已被定义运行结果:FLAG未被定义条件编译# if 表达式 程序段1 # else 程序段2 # endif #if形式:使用常量表达式的值作为编译条件作用:当所指定的表达式为真(非零)时就编译程序段1,否则编译程序段2。 可以事先给定一定条件,使程序在不同的条件下执行不同的功能。# if 表达式 程序段# endif 作用:当指定的表达式非零时编译程序段条件编

59、译【例】输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或改为小写字母输出。#include#define LETTER 1void main() char str20=“C Language”,c; int i=0; while(c=stri)!=0) i+; #if LETTER if(c=a & c=A & c=Z) c=c+32; #endif printf(“%c”,c); 预处理命令读程序,写结果1.#include#define Sqr(x) x*xvoid main() int a=15,b=2,m=1; a/=Sqr(b+m)/Sqr(b+m); prin

60、tf( %dn,a);结果:22.#include#define MIN(x,y) (x)(y)?(x):(y)void main() int a=1,b=5,c=4,d=4,t; t=MIN(a+b,c+d)*10; printf(%d,t);结果:6宏展开:(1+5)limit成立?#includelong series(int limit)long n=0;float sum=0;do +n; sum+=1.0/n;while(sum=limit);return n;void main( )long n=0;int limit;scanf(%d,&limit);n=series(limi

温馨提示

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

最新文档

评论

0/150

提交评论