C语言课件第八章_第1页
C语言课件第八章_第2页
C语言课件第八章_第3页
C语言课件第八章_第4页
C语言课件第八章_第5页
已阅读5页,还剩145页未读 继续免费阅读

下载本文档

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

文档简介

教学目与要求:明确C程序由一个或多个函数构成,掌握函数的定义方法,熟悉函数的传值调用,嵌套调用,递归调用的执行过程;掌握变量的类型,作用域,生存期等概念,正确使用动态变量,静态变量。教学内容:概述;函数定义的一般形式;函数的参数和函数的值;函数的调用;函数的嵌套调用;函数的递归调用;数组作为函数参数;局部变量和全局变量;变量的存储类别;内部函数和外部函数;如何运行一个多文件的程序。教学重点与难点:重点是函数的定义和调用,变量的作用域和生存期难点是函数的嵌套调用与递归调用。Ch8函数教学目与要求:Ch8函数1★特点:各模块相对独立、功能单一、结构清晰、接口简单控制了程序设计的复杂性缩短开发周期避免程序开发的重复劳动易于维护和功能扩充8.1概述C是模块化程序设计语言

★基本思想:将一个大的程序按功能分割成一些小模块★开发方法:自上向下,逐步细化★特点:8.1概述C是模块化程2一个C程序由一个或多个程序模块组成,每个程序模块作为一个源程序文件C是函数式语言,一个源程序文件由一个或多个函数以及其他有关内容组成.一个C程序必须有且只能有一个名为main的主函数C程序的执行总是从main函数开始,main函数结束时结束函数不能嵌套定义,可以嵌套调用,但不能调用main函数.所有子函数都是平行的,任何函数都不属于其他函数C是模块化程序设计语言C程序结构一个C程序由一个C是模块化程序设计语言C程序结构3函数分类从用户角度标准函数(库函数):由系统提供用户自定义函数从函数形式无参函数有参函数使用库函数应注意:1、函数功能2、函数参数的数目和顺序,及各参数意义和类型3、函数返回值意义和类型4、需要使用的包含文件函数分类使用库函数应注意:48.2函数定义的一般格式合法标识符函数返回值类型缺省int型无返回值void函数体类型标识符函数名(){

说明部分 语句部分}例空函数

dummy(){}函数体为空例无参函数

printstar(){printf(“**********\n”);}或

printstar(void){printf(“**********\n”);}8.2.1无参函数定义的一般格式8.2函数定义的一般格式合法标识符函数返回值类型函数体类型58.2.2有参函数定义的一般格式合法标识符函数返回值类型缺省int型无返回值void函数体类型标识符函数名(形参类型说明表){

说明部分 语句部分}例有参函数

intmax(intx,inty){intz;z=x>y?x:y;return(z);}例有参函数号

intmax(int

x,y){intz;z=x>y?x:y;return(z);}8.2.2有参函数定义合法标识符函数返回值类型函数体类型标6函数类型函数名(形参表)形参类型说明{

说明部分 语句部分}传统风格:例有参函数(传统风格)

intmax(x,y)

intx,y;{intz;z=x>y?x:y;return(z);}函数类型函数名(形参表)传统风格:例有参函数78.2.3空函数void函数名(){

}作用:在程序设计中往往根据需要确定若干模块,分别由一些函数实现,而在第一阶段中设计最基本的模块,其他一些次要功能或锦上添花的功能则在以后需要时陆续补上,在编写程序的开始阶段,可以在将来要扩充的地方写一个空函数.8.2.3空函数void函数名(88.3.1形参与实参形式参数:定义函数时函数名后面括号中的变量名实际参数:调用函数时函数名后面括号中的参数例比较两个数并输出大者max(intx,inty){intz;z=x>y?x:y;return(z);}main(){inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis%d",c);}8.3函数参数和函数的值说明:形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放实参可为常量,变量或表达式,但必须有确定的值,调用时实参的值传给形参.形参必须指定类型形参与实参类型一致,个数相同若形参与实参类型不一致,自动按形参类型转换———函数调用转换实参到形参是单向的值传递反过来不行.8.3.1形参与实参例比较两个数并输出大者max(int9例计算x的立方#include<stdio.h>floatcube(floatx){return(x*x*x);}main(){floata,product;printf("Pleaseinputvalueofa:");scanf("%f",&a);product=cube(a);printf(”Cubeof%.4fis%.4f\n",a,product);}xaproduct××××1.21.21.728例计算x的立方#include<stdio.h>xap10返回语句形式:return(表达式);或

return表达式;或

return;功能:使程序控制从被调用函数返回到调用函数中,同时把返回值带给调用函数说明:函数中可有多个return语句若无return语句,遇}时,自动返回调用函数,返回的是一个不确定的值若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换------函数调用转换void型函数没有返回值例无返回值函数

voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}8.3.2函数的返回值返回语句例无返回值函数8.3.2函数的返回值11

printstar(){printf("**********");}main(){inta;a=printstar();printf("%d",a);}例:下列函数的不同。voidprintstar(){printf("**********");}main(){inta;a=printstar();printf("%d",a);}**********10编译错误notanallowedtypeprintstar()例:下列函数的不同。void12例:函数返回值类型转换max(floatx,floaty){floatz;z=x>y?x:y;

return(z);}main(){floata,b;intc;scanf("%f%f",&a,&b);c=max(a,b);printf("Maxis%d\n",c);}例:函数返回值类型转换max(floatx,float13教学目与要求:熟悉函数的传值调用嵌套调用递归调用的执行过程;教学内容:函数的嵌套调用;函数的递归调用;数组作为函数参数;教学重点与难点:函数的嵌套调用与递归调用。Ch8函数(2)教学目与要求:Ch8函数(2)148.4函数的调用8.4.1调用的一般形式函数名(实参表列);说明:实参与形参个数相等,类型一致,按顺序一一对应实参表求值顺序,因系统而定(TurboC自右向左)8.4.2调用方式函数语句:例printstar();printf(“Hello,World!\n”);函数表达式:例m=max(a,b)*2;函数参数:例printf(“%d”,max(a,b));m=max(a,max(b,c));8.4函数的调用8.4.2调用方式15intf(inta,intb){intc;if(a>b)c=1;elseif(a==b)c=0;elsec=-1;return(c);}voidmain(){inti=2,p;p=f(i,++i);printf("%d",p);}例参数求值顺序intf(inta,intb){intc;if(a>b)c=1;elseif(a==b)c=0;elsec=-1;return(c);}voidmain(){inti=2,p;p=f(i,i++);printf("%d",p);}运行结果:0TC运行结果:1VC:0intf(inta,intb)例参数求值顺序in16对被调用函数要求:必须是已存在的函数库函数应该使用

#include<*.h>用户自定义函数或者在调用前面,或者先有函数类型说明告诉编译系统函数类型、参数个数及类型,以便检验函数定义与函数声明不同函数定义是指函数功能的确立,包括函数名、值、形参以及函数体,是一个完整的、独立的函数单位。函数声明告诉编译系统函数类型、参数个数及类型,以便检验8.4.3对被调用函数的声明和函数原型对被调用函数要求:8.4.3对被调用函数的声明和函数原型17例函数声明举例floatadd(floatx,floaty){floatz;z=x+y;return(z);}voidmain(){floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);}被调函数出现在主调函数之前,不必函数声明/*ch8-4.c*/voidmain(){floatadd(floatx,floaty);floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);}floatadd(floatx,floaty){floatz;z=x+y;return(z);}voidmain(){inta,b;intc;scanf("%f,%f",&a,&b);c=max(a,b);printf("Maxis%d\n",c);}max(intx,inty){intz;z=x>y?x:y;return(z);}int型函数可不作函数说声明(BorlandC++不行)例函数声明举例floatadd(floatx,fl188.4.3对被调用函数的声明和函数原型函数的声明简称函数原型.一般情况下,函数的声明与函数定义的第一行(函数首部)基本相同,但差一个分号,因此,可以简单地照写已经定义的函数的首部,再加一个分号,就成了声明。函数原型的形式

(1)函数类型函数名(形参类型1,形参类型2,…..形参类型n);

(2)函数类型函数名(形参类型1参数名1,形参类型2参数名2,…..,形参类型n参数名n);

编译系统不检查参数名,参数名是什么无所谓函数说明位置:程序的数据说明部分(函数内或外)下列情况下,可不作函数说明被调用函数定义出现在主调函数之前如果已经在头文件的开头(在所有函数之前)已经对本文件中所调用的函数进行了声明,则在各函数中不必再说明。若函数返值是char或int型,系统自动按int型处理8.4.3对被调用函数的声明和函数原型19intsum(inta,intb){a=a+b;b=a+b;return(a);}voidmain(){inta=1,b=3,c;c=sum(a,b);printf("%d,%d,%d",a,b,c);}例读程序写出程序结果。1,3,4voidmain(){floatadd(floata,floatb);floata,b,c;scanf("%f,%f",&a,&b);c=add(a,b);printf("sumis%f",c);}floatadd(floatx,floaty){floatz;z=x+y;return(z);}intsum(inta,intb)例读程序写出程208.5函数的嵌套调用main()调用函数a结束a函数b函数调用函数b嵌套调用C规定:函数定义不可嵌套,但可以嵌套调用函数,即在调用一个函数的过程中又调用另一个函数。8.5函数的嵌套调用main()调用函数a结束a函数b函21例求三个数中最大数和最小数的差值#include<stdio.h>

intdif(intx,inty,intz);intmax(intx,inty,intz);intmin(intx,inty,intz);voidmain(){inta,b,c,d;scanf("%d%d%d",&a,&b,&c);

d=dif(a,b,c);printf("Max-Min=%d\n",d);}intdif(intx,inty,intz){returnmax(x,y,z)-min(x,y,z);}intmax(intx,inty,intz){intr;r=x>y?x:y;return(r>z?r:z);}intmin(intx,inty,intz){intr;r=x<y?x:y;return(r<z?r:z);}main()调用函数dif输出结束dif函数max函数调用函数max调用函数minmin函数例求三个数中最大数和最小数的差值#include<s22floatfac(intk){floatt=1;inti;for(i=2;i<=k;i++)t*=i;returnt;}voidmain(){floatc;intm,n;scanf(“%d,%d”,&m,&n);

c=fac(n)/(fac(m)*fac(n-m));printf(“%f”,c);}例求分析:重复三次求阶乘运算,只是每次的值不同。将求阶乘的过程编成一个函数,以不同的参数值来调用函数。floatfac(intk)例求分析:重复三次求23说明:C编译系统对递归函数的自调用次数没有限制每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出

8.6

函数的递归调用定义:函数直接或间接的调用自身叫函数的递归调用f()调f调f2调f1f1()f2()intf(intx){inty,z;……z=f(y);…….return(2*z);}intf1(intx){inty,z;……

z=f2(y);…….return(2*z);}intf2(intt){inta,c;……

c=f1(a);…….return(3+c);}此两种递归都无法结束,应有某种条件控制递归调用结束。说明:8.6函数的递归调用f()调f调f2调f1f1(24例8.8intage(intn){intc;if(n==1)c=10;elsec=age(n-1)+2;return(c);}voidmain(){printf(“%d\n”,age(5);}age(5)=age(4)+1age(4)=age(3)+1age(3)=age(2)+1age(2)=age(1)+1age(1)=10age(2)=12age(3)=14age(4)=16age(5)=18例8.8intage(intn)age(5)age(425例8.8求n的阶乘/*ch8_8.c*/#include<stdio.h>floatfac(intn){floatf;if(n<0)printf("n<0,dataerror!");elseif(n==0||n==1)f=1;elsef=fac(n-1)*n;return(f);}voidmain(){intn;floaty;printf("Inputaintegernumber:");scanf("%d",&n);

y=fac(n);printf("%d!=%15.0f",n,y);}例8.8求n的阶乘/*ch8_8.c*/26递归调用的实现主程序(1)输出f(4);

……4

f(4);(1)n=4top(2)s=4*f(3)n3

f(3);(2)n=3(1)n=4top(3)s=3*f(2)n2

f(2);(3)n=2(2)n=3(1)n=4top(4)s=2*f(1)n1(4)n=1(3)n=2(2)n=3(1)n=4tops

s=3*2*1;(2)3(1)4top

s=2*1(3)2(2)3(1)4top

s=4*3*2*1(1)4top返回(3)2(2)3(1)4top(4)1结束输出24递归调用的实现主程序(1)输出f(4);……4f27例:用数组求Fibonacci数列前20个数longintfac(intn){longintf;if(n==1||n==2)f=1;elsef=fac(n-1)+fac(n-2);returnf;}voidmain(){inti;for(i=1;i<=40;i++){printf("%12ld",fac(i));if(i%4==0)printf("\n");}getch();}例:用数组求Fibonacci数列前20个数longint28例Hanoi问题ABC例Hanoi问题ABC29例Hanoi问题voidmove(chargetone,charputone){printf("%c--->%c\n",getone,putone);}voidhanoi(intn,charone,chartwo,charthree){if(n==1)move(one,three);else{hanoi(n-1,one,three,two); move(one,three);

hanoi(n-1,two,one,three);}}main(){intm;printf("Inputthenumberofdisks:");scanf("%d",&m);printf("Thestepstomoving%3ddisks:\n",m);hanoi(m,'A','B','C');}ABC从上面分析可以看出,当n大于等于2时,移动的过程可分解为三个步骤:第一步把A上的n-1个圆盘移到B上;第二步把A上的一个圆盘移到C上;第三步把B上的n-1个圆盘移到C上;其中第一步和第三步是类同的。本题算法分析如下,设A上有n个盘子。如果n=1,则将圆盘从A直接移动到C。如果n=2,则:1.将A上的n-1(等于1)个圆盘移到B上;2.再将A上的一个圆盘移到C上;3.最后将B上的n-1(等于1)个圆盘移到C上。如果n=3,则:A.将A上的n-1(等于2,令其为n`)个圆盘移到B(借助于C),步骤如下:(1)将A上的n`-1(等于1)个圆盘移到C上。(2)将A上的一个圆盘移到B。(3)将C上的n`-1(等于1)个圆盘移到B。B.将A上的一个圆盘移到C。C.将B上的n-1(等于2,令其为n`)个圆盘移到C(借助A),步骤如下:(1)将B上的n`-1(等于1)个圆盘移到A。(2)将B上的一个盘子移到C。(3)将A上的n`-1(等于1)个圆盘移到C。到此,完成了三个圆盘的移动过程。例Hanoi问题voidmove(chargeto30【举例】将从键盘输入的字符序列逆置输出,用递归函数来实现。比如,从键盘上输入:ABCD回车;算法将输出:DCBA。voidReversed(){charch;ch=getchar();if(ch!=‘\n’)reversed();if(ch!=‘\n’)printf(“%c”,ch);}【举例】将从键盘输入的字符序列逆置输出,用递归函数来实现。比31【举例】将从键盘输入的十进制正整数以二进制形式输出。用递归函数来实现。比如,从键盘上输入:13回车;算法将输出:1101。#include<stdio.h>voidmain(){intn;voidbin(int);scanf("%d",&n);bin(n);}voidbin(intn){intr;r=n%2;n=n/2;if(n!=0)bin(n);printf("%d",r);}【举例】将从键盘输入的十进制正整数以二进制形式输出。用递归函32函数的递归调用小结用递归法编写函数的方法

(1)分解:将原问题分解为若干小问题,其中至少有一个小问题与原问题性质完全相同;

(2)找递归出口(即递归结束条件):利用出口的结果逐步回代即可得到原问题的解。递归法的优点

(1)编写的程序比较简洁清楚,增加了可读性;

(2)有些问题(如Hanoi塔问题)用其他方法较难而用递归方法较易;

(3)便于进行算法的复杂性分析。递归法的缺点:时间和空间的代价较大。

注:递归算法都可以转换为非递归算法。函数的递归调用小结用递归法编写函数的方法

(1)分解:将原问33作业8.48.58.68.7作业8.434教学目与要求:理解数组作为函数参数;理解局部变量和全局变量;了解变量的存储类别和内部函数和外部函数;知道如何运行一个多文件的程序。教学内容:数组作为函数参数;局部变量和全局变量;变量的存储类别;内部函数和外部函数;如何运行一个多文件的程序。教学重点与难点:重点是数组作为函数参数,变量的作用域和生存期是难点Ch8函数(3)教学目与要求:Ch8函数(3)358.7数组作为函数参数★

函数参数传递方式值传递方式方式:函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值特点:形参与实参占用不同的内存单元单向传递#include<stdio.h>swap(inta,intb){inttemp;temp=a;a=b;b=temp;}voidmain(){intx=7,y=11;

swap(x,y);printf("x=%d,\ty=%d\n",x,y);}地址传递方式:函数调用时,将数据的存储地址作为参数传递给形参特点:形参与实参占用同样的存储单元“双向”传递实参和形参必须是地址常量或变量8.7数组作为函数参数★函数参数传递方式值传递方式#in368.7.1数组元素作函数实参—值传递8.7数组作为函数参数intmax(intx,inty){return(x>y?x:y);}voidmain(){inta[10],i,m;for(i=0;i<10;i++)scanf(“%d”,&a[i]);m=a[0];for(i=1;i<10;i++)

m=max(m,a[i]);

printf(“max=%d”,m);}若函数的形参是数组,对应的实参必须是数组名或指针变量。intmax(intx[10]){inti,m=x[0];for(i=1;i<10;i++)if(m<x[i])m=x[i];returnm;}voidmain(){inta[10],i;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“max=%d”,max(a));}说明:应该在主调函数和被调函数中分别定义数组,不能只在一方定义.实参数组与形参数组的类型必须一致用数组名做参数时,传递的是数组的首地址,形参数组的大小不起作用.形参数组可以不指定大小,只用一个方括号,可另设一参数,传递数组元素的个数数组做函数参数时,形参数组和实参数组共享同一内存单位例求10个任意整数中的最大值8.7.2数组名作函数参数—地址传递intmax(intx[],intn){inti,m=x[0];for(i=1;i<n;i++)if(m<x[i])m=x[i];returnm;}voidmain(){inta[10],i;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“max=%d”,max(a,10));}8.7.1数组元素作函数实参—值传递8.7数组作为函数参数37例求学生的平均成绩

#include<stdio.h>

floataverage(intstu[10],intn);voidmain(){intscore[10],i;floatav;printf("Input10scores:\n");for(i=0;i<10;i++)scanf("%d",&score[i]);av=average(score,10);printf("Averageis:%.2f",av);}floataverage(int

stu[10],intn){inti;floatav,total=0;for(i=0;i<n;i++)total+=stu[i];av=total/n;returnav;}实参用数组名形参用数组定义,intstu[]..2109score562312….….88stu例求学生的平均成绩#include<stdio.h>38数组排序----简单选择排序voidsort(intarray[],intn){inti,j,k,t;for(i=0;i<n-1;i++){k=i; for(j=i+1;j<n;j++) if(array[j]<array[k])k=j; if(k!=i) {t=array[i]; array[i]=array[k]; array[k]=t; }}}voidmain(){voidsort(intarray[],intn);inta[10],i;for(i=0;i<10;i++) scanf("%d",&a[i]);

sort(a,10);for(i=0;i<10;i++)printf("%d",a[i]);}0123456789a4968573299927137688arraykjjjkjkjjjjj949i=0数组排序----简单选择排序voidsort(inta39例数组排序----简单选择排序voidsort(intarray[],intn){inti,j,k,t;for(i=0;i<n-1;i++){k=i; for(j=i+1;j<n;j++) if(array[j]<array[k])k=j; if(k!=i) {t=array[i]; array[i]=array[k]; array[k]=t; }}}main(){voidsort(intarray[],intn);inta[10],i;for(i=0;i<10;i++) scanf("%d",&a[i]);

sort(a,10);for(i=0;i<10;i++)printf("%d",a[i]);printf("\n");}kjjkjkjjjjj0123456789a4968573299927137688array949kk1368i=1例数组排序----简单选择排序voidsort(int40例数组元素与数组名作函数参数比较12a调用前a[0]a[1]12a调用a[0]a[1]12xy21xy交换12a返回#include<stdio.h>voidswap2(intx,inty){intz;z=x;x=y;y=z;}main(){inta[2]={1,2};

swap2(a[0],a[1]);printf("a[0]=%d\na[1]=%d\n",a[0],a[1]);}值传递例数组元素与数组名12a调用前a[0]a[1]12a调4112a调用前12ax调用21ax交换21a返回#include<stdio.h>voidswap2(intx[]){intz;z=x[0];x[0]=x[1];x[1]=z;}main(){inta[2]={1,2};

swap2(a);printf("a[0]=%d\na[1]=%d\n",a[0],a[1]);}地址传递例数组元素与数组名作函数参数比较12a调用前12ax调用21ax交换21a返回#includ428.7.1数组元素作函数实参—值传递8.7数组作为函数参数8.7.2一维数组作函数参数—地址传递intmax(intx[][4]){inti,j,m=x[0][0];for(i=0;i<3;i++)for(j=0;j<4;j++)if(m<x[i][j])m=x[i][j];returnm;}voidmain(){inta[3][4]={1,3,5,7,9,2,4,6,8,10,15,13,17,5};printf(“max=%d”,max(a));}1.多数数组元素可以作为函数的参数2.如果形参是多维数组,可以省略第一维的大小,但不能省略其他维的大小。8.7.3多维数组与函数参数intmax(intx[3][4])intmax(intx[][4])intmax(intx[3][])(×)intmax(intx[][])(×)例:有一个3×4的矩阵,求最大元素的值。8.7.1数组元素作函数实参—值传递8.7数组作为函数参数43例求二维数组中各行元素之和get_sum_row(intx[][3],intresult[],introw,intcol){inti,j;for(i=0;i<row;i++){result[i]=0; for(j=0;j<col;j++) result[i]+=x[i][j];}}main(){inta[2][3]={3,6,9,1,4,7};intsum_row[2],row=2,col=3,i;

get_sum_row(a,sum_row,row,col);for(i=0;i<row;i++)printf("Thesumofrow[%d]=%d\n",i+1,sum_row[i]);}314679asum_rowxresult1812例求二维数组中各行元素之和get_sum_row(int448.8.1局部变量---内部变量定义:在函数内定义,只在本函数内有效说明:main中定义的变量只在main中有效不同函数中同名变量,占不同内存单元形参属于局部变量在一个函数内,可定义在复合语句中有效的变量局部变量可用存储类型:autoregisterstatic

(默认为auto)floatf1(inta){intb,c;…….}charf2(intx,inty){inti,j;……}main(){intm,n;…….}a,b,c有效x,y,i,j有效m,n有效运行结果:54321例:复合语句中的变量#defineN5main(){inti;inta[N]={1,2,3,4,5};for(i=0;i<N/2;i++)

{

inttemp; temp=a[i]; a[i]=a[N-i-1]; a[N-i-1]=temp;

}for(i=0;i<N;i++)printf("%d",a[i]);}例不同函数中同名变量main(){inta,b;a=3;b=4;printf("main:a=%d,b=%d\n",a,b);sub();printf("main:a=%d,b=%d\n",a,b);}sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=48.8局部变量和全局变量8.8.1局部变量---内部变量floatf1(int458.8.2全局变量---外部变量定义:在函数外定义,可为本文件所有函数共用有效范围:从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件应尽量少使用全局变量,因为:全局变量在程序全部执行过程中占用存储单元降低了函数的通用性、可靠性,可移植性降低程序清晰性,容易出错

定义

说明次数:只能1次可说明多次位置:所有函数之外函数内或函数外分配内存:分配内存,可初始化不分配内存,不可初始化外部变量说明:

extern数据类型变量表;外部变量定义与外部变量说明不同若外部变量与局部变量同名,则外部变量被屏蔽外部变量可用存储类型:缺省

static全局变量增加了函数间数据联系的渠道,通过函数调用可得到一个以上的值,一般将全局变量名的第一个字母大写;8.8.2全局变量---外部变量应尽量少使用全局变量,因为46#include<stdio.h>floatMax,Min;floataverage(floatarray[],intn){inti;floatsum=Max=Min=array[0];for(i=1;i<n;i++){if(array[i]>max)

Max=array[i];elseif(array[i]<min)Min=array[i];sum+=array[i];}return(sum/n);}main(){inti;floatave,score[10];/*Input*/ave=average(score,10);printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n",Max,Min,ave);}作用域maxmin#include<stdio.h>作用域maxmin47#include<stdio.h>inta=3,b=5;/*a,b外部变量voidmain(){intmax(inta,intb);/*本行是函数声明,a,b为形参inta=8;/*a为局部变量局部变量a作用范围printf(“%d\n”,max(a,b));局部变量b作用范围}intmax(inta,intb)/*a,b为形参局部变量{intc;c=a>b?a:b;return(c);}形参a,b作用范围#include<stdio.h>形参a,b作用范围488.9变量的存储类别内存…….main(){inta;a=10;printf(“%d”,a);}编译或函数调用时为其分配内存单元1020002019程序中使用变量名对内存操作概述变量是对程序中数据的存储空间的抽象。变量的属性数据类型:变量所持有的数据的性质(操作属性)存储属性存储器类型:寄存器、静态存储区、动态存储区作用域:变量在程序中的作用范围----局部变量与全局变量生存期:变量占用内存单元的时间----静态存储与动态存储8.9变量的存储类别内存…….main()编译或函数调用时498.9.1动态变量与静态变量存储方式静态存储:编译时为其分配的,程序运行期间占有该固定存储空间,直到程序运行结束。动态存储:程序运行期间根据需要动态分配存储空间。内存用户区程序区静态存储区动态存储区全局变量、局部静态变量形参变量局部动态变量(auto,register)函数调用现场保护和返回地址等生存期静态变量:从程序开始执行到程序结束动态变量:从包含该变量定义的函数开始执行至函数执行结束8.9变量的存储类别8.9.1动态变量与静态变量程序区静态存储区动态存储区全局508.9.2auto-----自动型

函数中的局部变量(如不专门声明为static存储类别)、函数中的形参和在函数中定义的变量,在调用函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。这类局部变量称为自动变量。用关键字auto作存储类别的声明,可省略。intf(inta){autointb,c=3;...}8.9变量的存储类别8.9.2auto-----自动型intf(int518.9.3static------静态型有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即占有存储单元不释放,在下一次该函数调用时,该变量已有值,是上一次函数调用结束时的值。这时就应该指定局部变量为“静态局部变量”,用关键字static进行声明。

#include<stdio.h>voidmain(){intf(int);inta=2,i;for(i=0;i<3;i++)printf("%d",f(a));}intf(inta){autointb=0;staticintc=3;b=b+1;c=c+1;return(a+b+c);}8.9变量的存储类别7898.9.3static------静态型#includ528.9.3static---静态型的说明属于静态存储类别静态局部变量在编译时赋初值,即只赋初值一次不赋初值的话,则对静态局部变量来说,编译时自动赋初值0或空字符

在函数调用结束后仍然存在,但其他函数不能引用它#include<stdio.h>voidmain(){inti;intfac(intn);for(i=1;i<=5;i++)printf("%d!=%d\n",i,fac(i));}intfac(intn){staticintf=1;f=f*n;return(f);}8.9变量的存储类别8.9.3static---静态型的说明#includ538.9.4register------存器变量

为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫“寄存器变量”,用关键字register作声明。只有局部自动变量和形式参数可以作为寄存器变量;不能定义任意多个寄存器变量;局部静态变量不能定义为寄存器变量。

#include<stdio.h>intfac(intn){registerinti,f=1;for(i=1;i<=n;i++)f=f*i;return(f);}voidmain(){inti;for(i=0;i<=5;i++)printf("%d!=%d\n",i,fac(i));}8.9变量的存储类别8.9.4register------存器变量#in548.9.5用extern声明外部变量

外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。

1.在一个文件内声明外部变量#include<stdio.h>voidmain(){intmax(int,int);externA,B;printf("%d\n",max(A,B));}intA=13,B=-8;intmax(intx,inty){intz;z=x>y?x:y;return(z);}8.9变量的存储类别8.9.5用extern声明外部变量#include<s558.9.5用extern声明外部变量

2.在多个文件的程序中声明外部变量#include<stdio.h>intA;voidmain(){intpower(int);intb=3,c,d,m;printf(“Enter:\n”);scanf(“%d%d”,&A,&m);C=A*b;printf(“%d*%d\n”,A,b,c);d=power(m);printf(“%d**%d\n”,A,m,d);}8.9变量的存储类别file1.c#include<stdio.h>externA;intpower(intn);{inti,y=1;for(i=1;i<=n;i++)y*=A;return(y);}file2.c8.9.5用extern声明外部变量#include<s568.9.6用static声明静态外部变量在程序设计时希望某些外部变量中限于本文件中使用,而不能被其他文件使用.可在定义外部变量时加一个static声明staticintA;voidmain(){…}8.9变量的存储类别file1.cexternintA;voidfun(intn){…A=A*n;}file2.c8.9.6用static声明静态外部变量statici578.9.7变量的声明和定义关于函数的声明和定义变量的声明和定义建立存储空间的声明称定义不需要建立存储空间的声明叫声明.8.9变量的存储类别8.9.7变量的声明和定义8.9变量的存储类别58静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区寄存器局部变量外部变量作用域定义变量的函数或复合语句内本文件其它文件局部变量默认为auto型register型变量个数受限,且不能为long,double,float型局部static变量具有全局寿命和局部可见性局部static变量具有可继承性extern不是变量定义,可扩展外部变量作用域register局部staticauto外部static外部存储类别8.9.8存储类别小结静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译59例文件file1.cinta;main(){…….f2;…….f1;…….}f1(){autointb;………f2;……..}f2(){staticintc;………}C作用域b作用域a作用域mainf2f1mainf1f2maina生存期:b生存期:c生存期:例文件file1.cC作用域b作用域a作用域mainf60intp=1,q=5;floatf1(inta){intb,c;…….}intf3(){…..}charc1,c2;charf2(intx,inty){inti,j;……}main(){intm,n;…….}c1,c2的作用域p,q的作用域externcharc1,c2;externcharc1,c2;c1,c2的作用域扩展后c1,c2的作用域扩展后intp=1,q=5;c1,c2的作用域p,q的作用域e61例外部变量定义与说明intmax(intx,inty){intz;z=x>y?x:y;return(z);}main(){externinta,b;printf("max=%d",max(a,b));}inta=13,b=-8;运行结果:max=13externinta,b;intmax(){intz;z=a>b?a:b;return(z);}main(){printf("max=%d",max());}inta=13,b=-8;例外部变量定义与说明intmax(intx,in62/*ch8_17.c*/inta=3,b=5;max(inta,intb){intc;c=a>b?a:b;return(c);}main(){inta=8;printf("max=%d",max(a,b));}例外部变量与局部变量运行结果:max=8/*ch8_17.c*/例外部变量与局部变量运行结果:m63inti;main(){voidprt();for(i=0;i<5;i++)prt();}voidprt(){for(i=0;i<5;i++)printf(“%c”,’*’);printf(“\n”);}例外部变量副作用运行结果:*****inti;例外部变量副作用运行结果:*****64例auto变量的作用域main(){intx=1;voidprt(void);

{

intx=3;prt();printf(“2ndx=%d\n”,x);

}printf(“1stx=%d\n”,x);}voidprt(void){intx=5;printf(“3thx=%d\n”,x);}运行结果:3thx=52ndx=31stx=1x=1作用域x=1作用域x=3作用域x=5作用域例auto变量的作用域main()运行结果:x=1作用65main(){voidincrement(void);increment();increment();increment();}voidincrement(void){intx=0;x++;printf(“%d\n”,x);}例局部静态变量值具有可继承性运行结果:111main(){voidincrement(void);increment();increment();increment();}voidincrement(void){staticintx=0;x++;printf(“%d\n”,x);}运行结果:123main()例局部静态变量值具有可继承性运行结果:1m66例变量的寿命与可见性inti=1;main(){staticinta;

registerintb=-10;intc=0;printf("-----MAIN------\n");printf("i:%da:%db:%dc:%d\n",i,a,b,c);c=c+8;

other();printf("-----MAIN------\n");printf("i:%da:%db:%dc:%d\n",i,a,b,c);i=i+10;other();}other(){staticinta=2;staticintb;

intc=10;a=a+2;i=i+32;c=c+5;printf("-----OTHER------\n");

printf("i:%da:%db:%dc:%d\n",i,a,b,c);b=a;}-------Main------i:1a:0b:-10c:0------Other------i:33a:4b:0c:15-------Main-----i:33a:0b:-10c:8-------Other-------i:75a:6b:4c:15全局i1main:a0b:-10registermain:c0静态存储区动态存储区other:a2other:b0other:c10843315443other:c10675156例变量的寿命与可见性inti=1;other()---67main(){voidgx(),gy();

externintx,y;printf(“1:x=%d\ty=%d\n”,x,y);y=246;gx();gy();}voidgx(){externintx,y;x=135;printf(“2:x=%d\ty=%d\n”,x,y);}intx,y;voidgy(){printf(“3:x=%d\ty=%d\n”,x,y);}例用extern扩展外部变量作用域运行结果:1:x=0y=02:x=135y=2463:x=135y=246main()例用extern扩展外部变量作用域运行结果:68例引用其它文件中的外部变量intglobal;externfloatx;main(){intlocal; . . .}externintglobal;staticintnumber;func2(){ . . .}floatx;staticintnumber;func3(){externintglobal; . . .}file1.cfile2.cfile3.c例引用其它文件中的外部变量intglobal;exter69例引用其它文件中的变量,输出ab和a的m次方inta;/*ch7-21.c*/main(){intpower(intn);intb=3,c,d,m;printf("Enterthenumberaanditspower:\n");scanf("%d,%d",&a,&m);c=a*b;printf("%d*%d=%d\n",a,b,c);d=power(m);printf("%d**%d=%d",a,m,d);}/*ch7-22.c*/externinta;intpower(intn){inti,y=1;for(i=1;i<=n;i++) y*=a;return(y);}例引用其它文件中的变量,输出ab和a的m次方inta70

inti=1;

main()/*lec9-7*/

{inti,j;i=reset();

for(j=1;j<=3;j++)

{printf("i=%d,j=%d\n",i,j);

printf("next(i)=%d\n",next(i));

printf("last(i)=%d\n",last(i));

printf("new(i+j)=%d\n",new(i+j));

}

}intreset()

{return(i);}intnext(int

j)

{j=i++;return(j);}intlast(intj)

{static

inti=10;

j=i--;

return(j);}intnew(inti)

{intj=10;

return(i=j+=i);}例:求下列程序运行结果i=1,j=1new(i)=1last(i)=10new(i+j)=12i=1,j=2next(i)=9new(i+j)=13i=1,j=3next(i)=3last(i)=8new(i+j)=14inti=1;

main()/*lec9-7*/

718.10内部函数与外部函数

8.10.1内部函数

函数首部:static返回值类型函数名(形参表)

作用域:只可被本文件中的函数调用。其它文件中可以有与其同名的函数,但互不干扰。

8.10.2外部函数

函数首部:extern返回值类型函数名(形参表)

作用域:可被其它文件中的函数调用。

注:一般extern可省,但在调用它的其它文件中要用extern进行声明。8.10内部函数与外部函数8.10.1内部函数

72作业8.98.108.118.15作业8.973例:一个程序由5个文件组成如何编译,连接和运行这个程序?/*f1.c*/externadd(int,int);externsub(int,int);externmult(int,int);externfloatdivs(int,int);intx,y;voidmain(){scanf("%d,%d",&x,&y);printf("\tadd=%d\n",add(x,y));printf("\tsub=%d\n",sub(x,y));printf("\tmult=%d\n",mult(x,y));printf("\tdivs=%f\n",divs(x,y));}/*f2.c*/externintx,y;add(intx,inty){returnx+y;}/*f3.c*/externintx,y;sub(intx,inty){returnx-y;}/*f4.c*/externintx,y;mult(intx,i

温馨提示

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

评论

0/150

提交评论