《C语言程序设计教程》课件--第7章.pptx

上传人:莉*** 文档编号:77674450 上传时间:2023-03-16 格式:PPTX 页数:76 大小:418.39KB
返回 下载 相关 举报
《C语言程序设计教程》课件--第7章.pptx_第1页
第1页 / 共76页
《C语言程序设计教程》课件--第7章.pptx_第2页
第2页 / 共76页
点击查看更多>>
资源描述

《《C语言程序设计教程》课件--第7章.pptx》由会员分享,可在线阅读,更多相关《《C语言程序设计教程》课件--第7章.pptx(76页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、2005年3月1第7章 函数与预处理命令 7.1 7.1 概述概述概述概述7.2 7.2 函数的定义与调用函数的定义与调用函数的定义与调用函数的定义与调用7.3 7.3 数组作函数参数数组作函数参数数组作函数参数数组作函数参数7.4 7.4 函数的嵌套调用和递归调用函数的嵌套调用和递归调用函数的嵌套调用和递归调用函数的嵌套调用和递归调用7.5 7.5 局部变量和全局变量及其作用域局部变量和全局变量及其作用域局部变量和全局变量及其作用域局部变量和全局变量及其作用域7.6 7.6 变量的存储类别及变量的生存期变量的存储类别及变量的生存期变量的存储类别及变量的生存期变量的存储类别及变量的生存期7.7

2、 7.7 函数的存储分类函数的存储分类函数的存储分类函数的存储分类7.8 7.8 编译预处理编译预处理编译预处理编译预处理7.9 7.9 多文件程序的调试方法多文件程序的调试方法多文件程序的调试方法多文件程序的调试方法第1页/共76页2005年3月27.1 概述 程序结构清晰,可读性好。程序结构清晰,可读性好。减少重复编码的工作量。减少重复编码的工作量。可多人共同编制一个大程序,缩短程序可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。设计周期,提高程序设计和调试的效率。使用函使用函数的数的好处好处C程序源程序文件n函数1函数m 源程序文件1函数1函数n第2页/共76页20

3、05年3月3【例7.1】求一个整数的立方。int cube(int x)int cube(int x)/*/*函数定义函数定义*/return(x*x*x);return(x*x*x);main()int f,a;printf(nEnter an integer number:);scanf(%d,&a);f=cube(a);cube(a);printf(%d*%d*%d=%dn,a,a,a,f);程序运行情况如下:Enter an integer number:2 2*2*2=8函数调用函数调用程序的执行总是从main函数开始第3页/共76页2005年3月4 一个C源程序可以由一个或多个源程

4、序文件组成。C编译系统在对C源程序进行编译时是以文件为单位进行的。一个C源程序文件可以由一个或多个函数组成。所有函数都是独立的。主函数可以调用其它函数,其它函数可以相互调用。在一个C程序中,有且仅有一个主函数main。C程序的执行总是从main函数开始,调用其它函数后最终回到main函数,在main函数中结束整个程序的运行。说明第4页/共76页2005年3月5 函数的种类从函数定义形式分:有参函数:在主调(用)函数和被调(用)函数之间通过参数进行数据传递,如:int cube(int x)无参函数:如:getchar()在调用无参函数时,主调函数不需要将数据传递给无参函数。从使用的角度看:从使

5、用的角度看:标准函数(库函数)标准函数(库函数)库函数是由系统提供的。库函数是由系统提供的。如:如:getchar()getchar()、sin(x)sin(x)等。等。在程序中可以直接调在程序中可以直接调用它们。附录用它们。附录A A列出了列出了C C的部分库函数。的部分库函数。用户自定义函数。用户自定义函数。如如:例例7.17.1中的中的cubecube函数。函数。第5页/共76页2005年3月6【例7.2】无参函数的定义与调用。void welcome()printf(*n);printf(Welcome to China n);printf(*n);main()welcome();程序

6、的输出结果如下:*Welcome to China*第6页/共76页2005年3月77.2.1 函数的定义函数定义的一般形式函数定义的一般形式函数类型 函数名(类型名 形式参数1,)说明语句 执行语句 例如:求两个数的最大值。int max(int x,int y)int z;z=x y?x:y;return(z);类型省略时默认为int类型没有形式参数为无参函数 第7页/共76页2005年3月8int max(x,y)int x,y;int z;z=x y?x:y;return(z);int max(x,y)int x,y;或int max(int x,y)或int max(x,y)int

7、x,y,z;z=x y?x:y;return(z);花括号中也可以为空,这种函数叫花括号中也可以为空,这种函数叫空函数空函数 。不能在函数体内定义其他函数,即函数不能在函数体内定义其他函数,即函数不能嵌套定义不能嵌套定义。形参也可以这样定义如下定义都是错误的如下定义都是错误的 第8页/共76页2005年3月9函数名(实参表列)在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。例如:welcome();if(iabs(a)max)max=iabs(a);m=max(c,max(a,b);7.2.2 函数的调用函数的调用函数调用的一般形式:第9页/共76页20

8、05年3月10int sum100()int i,t=0;for(i=1;i=100;i+)t+=i;return(t);main()int s;s=sum100();printf(%dn,s);程序输出结果:5050int sum(int x)int sum(int x)int i,t=0;int i,t=0;for(i=1;i=x;i+)for(i=1;iy?x:y;z=xy?x:y;return(z);/*return(z);/*返回返回z z的值的值*/main()main()int a,b,c;int a,b,c;scanf(%d,%d,&a,&b);scanf(%d,%d,&a,&

9、b);c=max(a,b);c=max(a,b);printf(max is%dn,c);printf(max is%dn,c);第14页/共76页2005年3月15函数的返回值是通过return语句带回到主调函数的功能:功能:终止函数的运行,返回主调函数,若有返回值,将返回值带回主调函数。说明:说明:若函数没有返回值,若函数没有返回值,returnreturn语句可以省略。语句可以省略。returnreturn语句中的表达式类型一般应和函数的类语句中的表达式类型一般应和函数的类型一致,型一致,如果不一致,系统自动将表达式类型转换为函数类型。函数的返回值函数的返回值return return

10、语句格式:语句格式:return return(表达式表达式););或或 return return 表达式表达式;或或 return;return;第15页/共76页2005年3月16【例例7.8】计算并输出圆的面积。计算并输出圆的面积。s(int r)return 3.14*r*r;main()int r,area;scanf(%d,&r);printf(%dn,s(r);自动转换自动转换为为intintintint型型 思考:思考:若要得到单精度实型的圆面积,程序应如何修改若要得到单精度实型的圆面积,程序应如何修改程序运行情况如下:2 12第16页/共76页2005年3月17 7.2.4

11、 对被调函数的声明和函数原型对被调函数的声明和函数原型变量要变量要先定义后使用先定义后使用,函数也如此函数也如此。即。即被调函数的被调函数的定义要出现在主调函数的定定义要出现在主调函数的定义之前义之前。如。如swapswapswapswap函数函数:允许整型函数(且参数允许整型函数(且参数也是整型)的定义出现在主也是整型)的定义出现在主调函数之后。如调函数之后。如maxmaxmaxmax函数函数:如果非整型函数在主调如果非整型函数在主调函数之后定义,则应在主调函数之后定义,则应在主调函数中或主调函数之前对函数中或主调函数之前对被被调函数进行声明。调函数进行声明。void swap(int x,

12、int y)main()swap(a,b);main()main()c=max(a,b);c=max(a,b);max(int x,int y)max(int x,int y)第17页/共76页2005年3月18对被调函数进行声明的一般形式 函数类型 函数名(参数类型1 参数名1,);或 函数类型 函数名(参数类型1,参数类型2,);思考思考思考思考:以下哪种情况需要以下哪种情况需要以下哪种情况需要以下哪种情况需要在主调函数中在主调函数中在主调函数中在主调函数中对被调函数对被调函数对被调函数对被调函数声明声明声明声明被调函数定义在前被调函数定义在前被调函数定义在前被调函数定义在前,主调函数定义

13、在后主调函数定义在后主调函数定义在后主调函数定义在后。主调函数定义在前主调函数定义在前主调函数定义在前主调函数定义在前,被调函数定义在后被调函数定义在后被调函数定义在后被调函数定义在后,且被调,且被调,且被调,且被调函数的类型不是整型的。函数的类型不是整型的。函数的类型不是整型的。函数的类型不是整型的。被调函数定义在后被调函数定义在后被调函数定义在后被调函数定义在后,但被调函数的类型是,但被调函数的类型是,但被调函数的类型是,但被调函数的类型是整型整型整型整型。第二种形式省略了参数名,此种形式也称为函数的原型。第18页/共76页2005年3月19main()void calc(float x,

14、float y,char opr);float a,b;char opr;printf(nInput expression:);scanf(%f%c%f,&a,&opr,&b);calc(a,b,opr);void calc(float x,float y,char opr)switch(opr)case +:printf(%5.2f%c%5.2f=%6.2fn,x,opr,y,x+y);return;case -:printf(%5.2f%c%5.2f=%6.2fn,x,opr,y,x-y);return;case *:printf(%5.2f%c%5.2f=%6.2fn,x,opr,y,x

15、*y);return;case /:printf(%5.2f%c%5.2f=%6.2fn,x,opr,y,x/y);return;default:printf(Operator err!n);对被调函数的声明【例7.9】计算并输出两个数的和、差、积、商。第19页/共76页2005年3月20 图 7.2 验证哥德巴赫猜想输入n的值 for(a=6;a=n;a+=2)for(b=3;b=a/2;b+=2)b是素数?T F c=a-b c是素数?T F 输出:a、b、c的值 break;【例例例例7.107.10】哥德巴赫猜想之一是任何一个大于哥德巴赫猜想之一是任何一个大于哥德巴赫猜想之一是任何一个

16、大于哥德巴赫猜想之一是任何一个大于5 5的偶的偶的偶的偶数都可以表示为两个素数之和。验证这一论断。数都可以表示为两个素数之和。验证这一论断。数都可以表示为两个素数之和。验证这一论断。数都可以表示为两个素数之和。验证这一论断。第20页/共76页2005年3月21#include math.h#include math.hint prime(int n);int prime(int n);main()main()int a,b,c,n;int a,b,c,n;scanf(%d,&n);scanf(%d,&n);for(a=6;a=n;a+=2)for(a=6;a=n;a+=2)for(b=3;b=

17、a/2;b+=2)for(b=3;b=a/2;b+=2)if(prime(b)if(prime(b)c=a-b;c=a-b;if(prime(c)if(prime(c)printf(%d=%d+%dn,a,b,c);printf(%d=%d+%dn,a,b,c);break;break;/*穷举法判断素数*/int prime(int n)int i;for(i=2;i=sqrt(n);i+)if(n%i=0)return 0;return 1;可以在main函数的前面对prime函数进行声明。实际上,该声明可以省略,为什么?程序如下:第21页/共76页2005年3月227.3 数组作函数参数

18、7.3.1 一维数组元素作函数参数main()int a5,i,m;for(i=0;i5;i+)scanf(%d,&ai);m=a0;for(i=1;i5;i+)m=min(m,ai);printf(%dn,m);【例7.11】求5个数中的最小值。int min(int x,int y)return(xy?x:y);用打擂台方法求最小用打擂台方法求最小用打擂台方法求最小用打擂台方法求最小值。值。值。值。mm相当于擂主相当于擂主相当于擂主相当于擂主第22页/共76页2005年3月237.3.2 一维数组名作函数参数数组名表示数组在内存中的起始地址。例如:数组a在内存中从2000地址开始存放,则a

19、的值为2000。2000是地址值,是指针类型的数据(第8中将介绍指针类型),不能把它看成是整型或其他类型数据。实参是数组名,形参也应定义为数组形式,形参数组的长度可以省略,但 不能省,否则就不是数组形式了。【例7.12】用冒泡法将10个整数排序。第23页/共76页2005年3月24void sort(int b,int void sort(int b,int n);n);void printarr(int b);void printarr(int b);main()main()int a10=int a10=11,22,63,97,58,80,411,22,63,97,58,80,45,32,

20、73,36;5,32,73,36;printf(Before printf(Before sort:n);sort:n);printarr(a);printarr(a);sort(a,10);sort(a,10);printf(After printf(After sort:n);sort:n);printarr(a);printarr(a);void printarr(int void printarr(int b10b10)int i;int i;for(i=0;i10;i+)for(i=0;i10;i+)printf(%5d,bi);printf(%5d,bi);printf(n);pr

21、intf(n);void sort(void sort(int b,int nint b,int n)int i,j,t;int i,j,t;for(i=1;in;i+)for(i=1;in;i+)for(j=0;jn-i;j+)for(j=0;jbj+1)if(bjbj+1)t=bj;bj=bj+1;bj+1=t;t=bj;bj=bj+1;bj+1=t;第24页/共76页2005年3月25 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b911 22 63 97 58 80 45 32 73 36(a)排序前a0 a1 a2

22、 a3 a4 a5 a6 a7 a8 a9b0 b1 b2 b3 b4 b5 b6 b7 b8 b911 22 32 36 45 58 63 73 80 97(b)排序后图7.3 调用sort函数2000b形参形参 b b 实际是一个实际是一个可以存放地址的变量可以存放地址的变量a:2000实参赋给形参首地址:2000首地址:2000第25页/共76页2005年3月26#include stdio.hmain()void scat(char str1,char str2);char s150,s250;int i,k;printf(Input s1:);gets(s1);printf(Inpu

23、t s2:);gets(s2);scat(s1,s2);printf(Output s1:%sn,s1);printf(Output s2:%sn,s2);void scat(char void scat(char str1,str1,char char str2)str2)int i=0,k=0;int i=0,k=0;while(str1i!=0)i+;while(str1i!=0)i+;while(str2k!=0)while(str2k!=0)str1i=str2k;str1i=str2k;i+;k+;i+;k+;str1i=0;str1i=0;scatscat函数还可简化为:函数还可

24、简化为:函数还可简化为:函数还可简化为:void scat(char str1,char str2)void scat(char str1,char str2)int i=0,k=0;int i=0,k=0;while(str1i)i+;while(str1i)i+;while(str1i+=str2k+);while(str1i+=str2k+);【例7.13】编程序,实现字符串连接。第26页/共76页2005年3月27以二维数组为例。二维数组名作实参时,对应以二维数组为例。二维数组名作实参时,对应的形参也应该定义为一个二维数组形式。对形参数的形参也应该定义为一个二维数组形式。对形参数组定义

25、时可以指定每一维的大小,也可以省略第一组定义时可以指定每一维的大小,也可以省略第一维的大小说明。维的大小说明。【例例7.147.14】编程序,将矩阵转置。设转置前为编程序,将矩阵转置。设转置前为a a矩阵,转置后为矩阵,转置后为b b矩阵,如下所示:矩阵,如下所示:a=a=1 2 3 4 1 2 3 4 5 6 7 85 6 7 89 10 11 129 10 11 121 1 5 5 9 92 2 6 6 10103 3 7 7 11114 4 8 8 1212b=b=思路:将思路:将a00a00b00b00,a01a01 b10 b10,a02a02b20b20,a10a10b01b01,

26、aijaijbjibji,。7.3.3 多维数组作函数参数多维数组作函数参数第27页/共76页2005年3月28void turn();main()int a34=1,2,3,4,5,6,7,8,9,10,11,12;int i,j,b43;turn(a,b);printf(array b:n);for(i=0;i4;i+)for(j=0;j3;j+)printf(%5d,bij);printf(n);/*/*矩阵转置函数矩阵转置函数矩阵转置函数矩阵转置函数*/void turn(int void turn(int arra 4,arra 4,int int arrbarrb 3)3)int

27、r,c;int r,c;for(r=0;r3;r+)for(r=0;r3;r+)for(c=0;c4;c+)for(c=0;c0;i-for(i=n;i0;i-)a+=a+=sub2(i);sub2(i);return a;return a;sub2(int n)sub2(int n)return n+1;return n+1;程序输出结果:9 第30页/共76页2005年3月317.4.2 函数的递归调用1递归的基本概念递归调用:一个函数直接或间接地调用了它本身,就称为函数的递归调用。递归函数:在函数体内调用该函数本身。int sub(int x)int y,z;if()z=sub(y);e

28、lse return;例如:直接调用sub函数本身第31页/共76页2005年3月322递归函数的执行过程【例7.16】编一递归函数求n!。思路:以求4的阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1。递归结束条件:当n=1或n=0时,n!=1。递归公式:n!=1 (n=0,1)n(n-1)!(n1)第32页/共76页2005年3月33程序如下:float fact(int n)float f=0;if(n0)printf(n0)再找出递归结束条件:当再找出递归结束条件:当n=0n=0n=0n=0时,时,x x x xn=1=1=1=1。第35页/共76页2005

29、年3月36程序如下:long xn(int x,int n)long f=0;if(n0)printf(n0,data error!n);else if(n=0)f=1;else f=x*xn(x,n-1);return(f);main()int n,x;long y;scanf(%d,%d,&x,&n);y=xn(x,n);printf(%ldn,y);程序运行情况如下:2,10 1024第36页/共76页2005年3月37 非数值型问题递归函数的编程方法有些问题不能直接用数学公式求解。非数值型问题比数值型问题更难找出递归的算法。它不能用一个递归公式表示。解决这类问题首先要把问题将大化小,将

30、繁化简。将一个复杂的问题化解成若干个相对简单的小问题,而某个小问题的解法与原问题解法相同,并且越来越简单直至有确定的解。【例例7.187.18】编制一递归函数,将一个十进制正整编制一递归函数,将一个十进制正整数(如:数(如:1561315613)转换成八进制数形式输出。)转换成八进制数形式输出。第37页/共76页2005年3月38思路:十进制整数转换成八进制整数的方法是除除8 8逆向取余逆向取余。如图7.5所示。余数:商:15613%8=5 15613/8=19511951%8=7 1951/8=243243%8=3243/8=3030%8=630/8=33%8=33/8=0结果:36375

31、图 7.5 十进制转换成八进制 非数值型问题递归函数的编程方法(续)第38页/共76页2005年3月39该题实际上是要把一个十进制数除以8得到的余数逆向输出。就是先得到的余数后输出,最后得到的余数最先输出。我们先由大化小:求八进制数变成求一系列余数的问题。求第一个余数是将15613除以8取余,因为先得到的余数后输出,所以把这个余数存在一个变量m中,接下去求下一个余数。和求第一个余数的方法相同,只是被除数变成了15613除以8的整数商1951。因此,这是一个递归调用的问题。定义变量m存放余数,x存放被除数。递归算法描述如下:非数值型问题递归函数的编程方法(续)第39页/共76页2005年3月40

32、 先求出余数m:m=x%8;求x除以8取余后的整数商:x=x/8;如果x不等于0,递归调用该函数,否则执行。输出余数m。返回调用点。非数值型问题递归函数的编程方法(续)第40页/共76页2005年3月41程序如下:#include stdio.hvoid dtoo(int x)int m;m=x%8;x=x/8;if(x!=0)dtoo(x);printf(%d,m);main()int n;scanf(%d,&n);printf(%d=(,n);dtoo(n);printf()8n);程序运行情况如下:15613 15613=(36375)8第41页/共76页2005年3月427.5 局部变

33、量和全局变量及其作用域7.5.1 变量的作用域7.5.2 局部变量及其作用域局部变量及其作用域变量的作用域:变量在程序中可以被使用的范围。根据变量的作用域可以将变量分为局部变量和全局变量。局部变量(内部变量内部变量):在函数内或复合语句内定义的变量以及形参形参。作用域:函数内或复合语句内。【例7.19】分析下面程序的运行结果及变量的作用域。问题:问题:一个变量在程序的哪个函数中都能使用吗?一个变量在程序的哪个函数中都能使用吗?第42页/共76页2005年3月43void sub(int a,int b)int c;a=a+b;b=b+a;c=b-a;printf(sub:ta=%d b=%d

34、c=%dn,a,b,c);局部变量局部变量main()int a=1,b=1,c=1;printf(main:ta=%d b=%d c=%dn,a,b,c);sub(a,b);printf(main:ta=%d b=%d c=%dn,a,b,c);int a=2,b=2;printf(comp:ta=%d b=%d c=%dn,a,b,c);printf(main:ta=%d b=%d c=%dn,a,b,c);局部变量局部变量局部变量局部变量“分程序”或“程序块”程序输出结果:main:a=1 b=1 c=1sub:a=2 b=3 c=1main:a=1 b=1 c=1comp:a=2 b=

35、2 c=1main:a=1 b=1 c=1第43页/共76页2005年3月447.5.3 全局变量及其作用域全局变量(外部变量):在函数外部定义的变量。作用域:从定义变量的位置开始到本源文件结束。如在其作用域内的函数或分程序中定义了同名局部变量,则在局部变量的作用域内,同名全局变量暂时不起作用。【例7.20】全局变量和局部变量的作用域。第44页/共76页2005年3月45int a=5;void f(int x,int y)int b,c;b=a+x;c=a-y;printf(%dt%dt%dn,a,b,c);局部变量局部变量main()int b=6,c=7;f(b,c);printf(%d

36、t%dt%dn,a,b,c);int a=9,b=8;printf(%dt%dt%dn,a,b,c);c=10;printf(%dt%dt%dn,a,b,c);printf(%dt%dt%dn,a,b,c);printf(%dt%dt%dn,a,b,c);局部变量局部变量局部变量局部变量程序输出结果:5 11 -25 6 79 8 79 8 109 8 105 6 10全局变量第45页/共76页2005年3月467.6 变量的存储类别及变量的生存期7.6.1 变量的生存期与变量的存储分类变量的生存期:变量在内存中占据存储空间的时间。思考思考思考思考:1.1.何时何时何时何时为变量分配内存单元为

37、变量分配内存单元为变量分配内存单元为变量分配内存单元?2.2.将变量分配在内存的什么将变量分配在内存的什么将变量分配在内存的什么将变量分配在内存的什么区域区域区域区域?3 3.变量占据内存的变量占据内存的变量占据内存的变量占据内存的时间时间时间时间(生存期生存期生存期生存期)?)?)?)?程序代码区静态存储区动态存储区存储分配动态存储变量静态存储变量第46页/共76页2005年3月477.6.2 变量的存储类别变量的属性数据类型:数据类型:决定为变量分配内存单元的长度,决定为变量分配内存单元的长度,数据的存放形式,数据的存放形式,数的范围。数的范围。存储类别:存储类别:决定了变量的生存期,决定

38、了变量的生存期,给它分配在哪个存储区。给它分配在哪个存储区。第47页/共76页2005年3月48变量定义语句的一般形式存储类别存储类别 数据类型数据类型 变量名变量名1,1,变量名变量名n;n;autoauto(自动的)(自动的)registerregister(寄存器的)(寄存器的)staticstatic(静态的)(静态的)externextern(外部的)(外部的)1自动变量(auto类别)局部变量可以定义为自动变量。main()int x,y;main()auto int x,y;自动变量自动变量等价可省第48页/共76页2005年3月49 内存分配内存分配调用函数或执行分程序时在动态

39、存储区动态存储区为其分配存储单元,函数或分程序执行结束,所占内存空间即刻释放。变量的初值变量的初值定义变量时若没赋初值,变量的初值不确定初值不确定;如果赋初值则每次函数被调用时执行一次赋值操作。生存期生存期 在函数或分程序执行期间。作用域作用域自动变量所在的函数内或分程序内。自动变量第49页/共76页2005年3月502静态变量(static类别)除形参外,局部变量和全局变量都可以定义为静态变量。局部静态变量(或称内部静态变量)局部静态变量(或称内部静态变量)全局静态变量(或称外部静态变量)静态变量静态变量静态变量静态变量static int a;main()float x,y;f()stat

40、ic int b=1;全局静态变量局部静态变量局部静态变量自动变量自动变量不能省第50页/共76页2005年3月51 内存分配内存分配编译时,将其分配在内存的静态存储区中,程序运行结束释放该单元。静态变量的初值静态变量的初值若定义时未赋初值,在编译时,系统自动赋初值为0;若定义时赋初值,则仅在编译时赋初值一次,程序运行后不再给变量赋初值。生存期生存期整个程序的执行期间。作用域作用域局部静态变量的作用域是它所在的函数或分程序。全局静态变量的作用域是从定义处开始到本源文件结束。静态变量第51页/共76页2005年3月52int c;static int a;main()float x,yx,y;c

41、har s;f()static int b=1;3.外部变量(extern类别)在函数外定义的变量若没有用 static说明,则是外部变量。外部变量只能隐式定义为extern类别,不能显式定义。全局静态变量自动变量自动变量局部静态变量局部静态变量外部变量第52页/共76页2005年3月53 内存分配内存分配编译时,将其分配在静态存储区,程序运行结束释放该单元。变量的初值变量的初值若定义变量时未赋初值,在编译时,系统自动赋初值为0。生存期生存期整个程序的执行期间。作用域作用域从定义处开始到本源文件结束。此外,还可以用此外,还可以用externextern进行声明,以进行声明,以使其作用域扩大到该

42、程序的其它文件中。使其作用域扩大到该程序的其它文件中。外部变量问题:问题:全局静全局静态变量态变量的作用的作用域可以域可以扩展到扩展到本程序本程序的其它的其它文件吗文件吗?第53页/共76页2005年3月54外部变量声明的一般格式 externextern 数据类型数据类型 变量名变量名1 1,变量名,变量名n n;或或 externextern 变量名变量名1 1,变量名,变量名n n;注意:注意:外部变量声明用关键字外部变量声明用关键字externextern,而外部变量的,而外部变量的定义不能用定义不能用externextern,只能隐式定义。,只能隐式定义。定义外部变量时,系统要给变量

43、分配存储空间,定义外部变量时,系统要给变量分配存储空间,而对外部变量声明时,系统不分配存储空间,而对外部变量声明时,系统不分配存储空间,只是让编译系统知道该变量是一个已经定义过只是让编译系统知道该变量是一个已经定义过的外部变量,与函数声明的作用类似。的外部变量,与函数声明的作用类似。第54页/共76页2005年3月55int p=1,q=5;float f1(int a)extern char c1,c2;char c1,c2;char f2(int x,int y)main()外部变量声明定义外部变量定义外部变量定义外部变量定义外部变量思考:思考:在在f1函数中声明函数中声明c1、c2的作用

44、是什么?如何修改的作用是什么?如何修改程序使所有函数都可以使用程序使所有函数都可以使用外部变量而又不需要声明?外部变量而又不需要声明?【例例7.24】在一个文件内声明外部变量。在一个文件内声明外部变量。第55页/共76页2005年3月56【例例7.25】在多文件的程序中声明外部变量。在多文件的程序中声明外部变量。file1.cfile1.c文件中程序如下:文件中程序如下:int i;main()void f1(),f2(),f3();i=1;f1();printf(tmain:i=%d,i);f2();printf(tmain:i=%d,i);f3();printf(tmain:i=%dn,i

45、);void f1()i+;printf(nf1:i=%d,i);file2.c文件中程序如下:文件中程序如下:extern int i;void f2()int i=3;printf(nf2:i=%d,i);void f3()i=3;printf(nf3:i=%d,i);程序输出结果:f1:i=2 main:i=2f2:i=3 main:i=2f3:i=3 main:i=3声明外部变量定义外部变量第56页/共76页2005年3月574.寄存器变量(register类别)只有函数内定义的变量或形参函数内定义的变量或形参可以定义为寄存器变量。寄存器变量的值保存在CPU的寄存器中。受寄存器长度的限

46、制,寄存器变量只能是寄存器变量只能是charchar、intint和指针类型的变量。和指针类型的变量。【例例7.26】寄存器变量的使用。寄存器变量的使用。main()long int sum=0;register int i;for(i=1;i(Y)?(X):(Y)7.8 编译预处理(续)第66页/共76页2005年3月677.8 编译预处理(续)【例7.30】带参数的宏定义。#define MAX(x,y)(x)(y)?(x):(y)(x)(y)?(x):(y)main()printf(%dn,a,b,MAX(a,b)MAX(a,b);printf(%dn,MAX(a+m,b+n)MAX(a

47、+m,b+n);分两次替换:将宏名MAX(a,b)MAX(a,b)替换成字符串(x)(y)?(x):(y)(x)(y)?(x):(y)。用实参a替换形参x,实参b替换形参y。程序中的两个printf语句被展开为:printf(%dn,(a)(b)?(a):(b);printf(%dn,(a+m)(b+n)?(a+m):(b+n);第67页/共76页2005年3月687.8 编译预处理(续)【例7.31】分析下面程序运行后的输出结果。#define MA(x)x*(x-1)x*(x-1)main()int a=1,b=2;printf(%dn,MA(1+a+b)MA(1+a+b);分两次替换:M

48、A(1+a+b)MA(1+a+b)用x*(x-1)x*(x-1)替换。用1+a+b替换x。printf语句被展开为:printf(%dn,1+a+b*(1+a+b-1);特别注意:由于替换文本中的x没有用括号括起,因此,1+a+b也不能用括号括起。程序输出结果:8第68页/共76页2005年3月697.8 编译预处理(续)命令的一般形式命令的一般形式格式格式1 1:#include 格式格式2 2:#include 文件名文件名 7.8.3 文件包含文件包含文件包含是将指定的某个源文件的内容全部包文件包含是将指定的某个源文件的内容全部包含到当前文件中。用含到当前文件中。用includeincl

49、ude命令实现。命令实现。用用格式格式1 1,预处理程序仅在,预处理程序仅在TCINCLUDETCINCLUDE目录下查目录下查找指定文件。找指定文件。用用格式格式2 2,预处理程序首先在,预处理程序首先在当前目录中当前目录中查找指定查找指定文件,若找不到再到文件,若找不到再到TCINCLUDETCINCLUDE目录中查找。目录中查找。第69页/共76页2005年3月707.8 编译预处理(续)例如:调用例如:调用sin(x)sin(x)函数时,要在程序的开头使函数时,要在程序的开头使用如下命令:用如下命令:#include#include 在预处理时,用在预处理时,用math.hmath.h

50、文件内容替换文件内容替换#include#include 命令行。命令行。2功能在预处理时,将在预处理时,将includeinclude命令后指定文件的命令后指定文件的内容替换该命令行。内容替换该命令行。第70页/共76页2005年3月717.9 多文件程序的调试方法操作步骤如下:操作步骤如下:在TC 环境下建立一个工程文件(扩展名为扩展名为prjprj),设文件名为test.prj,文件内容如下:file1.cfile1.cfile2.cfile2.cfiile3.cfiile3.c若这个文件不在当前盘或当前路径下,需要在文件名前加盘符和路径。如果已经将源文件编译成目标文件,可在工程文件中直

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > PPT文档

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com