1、模块化程序设计模块化程序设计u基本思想:将一个大的程序按功能分割成一些小模块基本思想:将一个大的程序按功能分割成一些小模块u特点:特点:各模块相对独立、功能单一、结构清晰、接口简单各模块相对独立、功能单一、结构清晰、接口简单控制了程序设计的复杂性控制了程序设计的复杂性提高元件的可靠性提高元件的可靠性缩短开发周期缩短开发周期避免程序开发的重复劳动避免程序开发的重复劳动易于维护和功能扩充易于维护和功能扩充u开发方法开发方法: 自上向下自上向下,逐步分解,分而治之逐步分解,分而治之C是模块化程序设计语言是模块化程序设计语言源程序文件1预编译命令说明部分执行部分函数1函数n源程序文件i源程序文件nC程
2、序C程序结构u C C是是函数式函数式语言语言(c7_1.cc7_1.c)u 必须有且只能有一个名为必须有且只能有一个名为mainmain的主函数的主函数u C C程序的执行总是程序的执行总是从从mainmain函数开始,在函数开始,在mainmain中结束中结束u 函数函数不能嵌套定义不能嵌套定义, ,可以可以嵌套嵌套调用调用函数分类函数分类u从用户角度从用户角度标准函数(库函数):由系统提供标准函数(库函数):由系统提供用户自定义函数用户自定义函数u从函数形式从函数形式无参函数无参函数有参函数有参函数使用使用库函数库函数应注意:应注意:1、函数功能、函数功能2、函数参数的数目和顺序,及各参
3、数意义和类型、函数参数的数目和顺序,及各参数意义和类型3、函数返回值意义和类型、函数返回值意义和类型4、需要使用的包含文件、需要使用的包含文件例例 无参函数无参函数 void printstar( ) printf(“*n”); 或或 void printstar(void ) printf(“*n”); 例例 有参函数(现代风格)有参函数(现代风格) int max(int x, y) int z; z=xy?x:y; return(z); 例例 空函数空函数dummy( ) 函数体为空函数体为空一般格式一般格式合法标识符函数返回值类型缺省int型无返回值void函数体函数类型函数类型 函数
4、名函数名(形参类型说明表形参类型说明表)说明部分说明部分语句部分语句部分u现代风格:现代风格:例例 有参函数(现代风格)有参函数(现代风格) int max(int x, int y) int z; z=xy?x:y; return(z); 函数类型函数类型 函数名(形参表)函数名(形参表)形参类型说明形参类型说明 说明部分说明部分 语句部分语句部分u传统风格传统风格: :例例 有参函数(传统风格)有参函数(传统风格) int max(x,y) int x,y; int z; z=xy?x:y; return(z); u说明:说明:实参必须有确定的值实参必须有确定的值形参必须指定类型形参必须指
5、定类型形参与实参形参与实参类型一致,个数相同类型一致,个数相同若形参与实参类型不一致,自动按形参类型转换若形参与实参类型不一致,自动按形参类型转换 函数调用转换函数调用转换参数传递方式为参数传递方式为值传递值传递方式:函数调用时方式:函数调用时,为形参分为形参分配单元配单元,并将实参的值并将实参的值复制复制到形参中;调用结束,形到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值。特参单元被释放,实参单元仍保留并维持原值。特点:形参与实参占用点:形参与实参占用不同不同的内存单元;的内存单元;单向单向传递传递8.3.1 形式参数与实际参数形式参数与实际参数u形式参数:定义函数时函数名后面
6、括号中的变量名形式参数:定义函数时函数名后面括号中的变量名u实际参数:调用函数时函数名后面括号中的表达式实际参数:调用函数时函数名后面括号中的表达式 c=max(a,b); (main 函数函数) (max 函数函数)max(int x,int y) int z; z=xy?x:y; return(z); 例例 比较两个数并输出大者比较两个数并输出大者#include (c7_2.c)void main(void) int a,b,c; int max(int x,int y); scanf(%d,%d,&a,&b); c=max(a,b); printf(Max is %d,c);int m
7、ax(int x,int y) int z; z=xy?x:y; return(z);形参形参实参实参例例 计算计算x的立方的立方#include float cube(float x) return(x*x*x);main() float a, product; printf(Please input value of a:); scanf(%f,&a); product=cube(a); printf(Cube of %.4f is %.4fn,a,product);x xa aproductproduct1.21.21.21.21.7281.7287 71111x:x:y:y:调用前:调
8、用前:调用结束:调用结束:7 71111x:x:y:y:例例 交换两个数交换两个数/*c7_3.c*/#include void main(void) int x=7,y=11; printf(x=%d,ty=%dn,x,y); printf(swapped:n); swap(x,y); printf(x=%d,ty=%dn,x,y);void swap(int a,int b) int temp; temp=a; a=b; b=temp;调用:调用:7 71111a:a:b:b:7 71111x:x:y:y:swap:swap:7 71111x:x:y:y:11117 7a:a:b:b:te
9、mptemp运行结果:运行结果:x=7, y=11 swapped: x=7, y=11值传递方式,单向传递值传递方式,单向传递u地址传递地址传递方式:函数调用时,将数据的方式:函数调用时,将数据的存储地址存储地址作为参数作为参数传递给形参传递给形参特点:特点: 形参与实参占用形参与实参占用同样同样的存储单元的存储单元 “双向双向”传递传递 实参和形参必须是实参和形参必须是地址地址常量或变量常量或变量/*ch9_3.c*/swap(p1,p2)int *p1,*p2; int p; p=*p1; *p1=*p2; *p2=p;main() int a,b; scanf(%d,%d,&a,&b)
10、; printf(“a=%d,b=%dn”,a,b); printf(“swapped:n”); swap(&a,&b); printf(”a=%d,b=%dn,a,b);例例 交换两个数交换两个数a59b调前:调前:a59b调调swap:p1&a&bp2a95b交换:交换:p1&a&bp2a95b返回:返回:8.3.2 函数的函数的返回值返回值返回语句返回语句u形式:形式: return(表达式表达式);或或 return 表达式表达式;或或 return;u功能:使程序控制从被调用函数返回到调用函数中,功能:使程序控制从被调用函数返回到调用函数中,同时把返同时把返回回值带给调用函数值带给调
11、用函数u说明:说明:函数中可有多个函数中可有多个return语句语句若无若无return语句,遇语句,遇 时,自动返回调用函数时,自动返回调用函数若若函数类型函数类型与与return语句中表达式值的类型不一语句中表达式值的类型不一致,按前者为准,自动转换致,按前者为准,自动转换-函数调用转换函数调用转换void型函数型函数用来明确表明函数不带回任何值用来明确表明函数不带回任何值例例 无返回值函数无返回值函数void swap(int x,int y ) int temp; temp=x; x=y; y=temp;例例8-3 函数返回值类型自动转换为函数类型函数返回值类型自动转换为函数类型#in
12、cludevoid main(void) float a,b; int c; int max(float x,float y); scanf(%f,%f,&a,&b); c=max(a,b); printf(Max is %dn,c);int max(float x, float y) float z; z=xy?x:y; return(z);运行结果:运行结果:1.5, 4.7Max is 4printstar() printf(*);main() int a; a=printstar(); printf(%d,a);例例 函数带回不确定值函数带回不确定值输出:输出:*10void prin
13、tstar() printf(*);main() int a; a=printstar(); printf(%d,a);编译错误!编译错误!8.4.1 函数调用的一般形式函数调用的一般形式u一般形式一般形式 : 函数名函数名(实参表实参表);u说明:说明:实参与形参实参与形参个数相等,类型一致,按顺序个数相等,类型一致,按顺序一一对应一一对应#include main() int i=2,p; int f(int a,int b); p=f(i,+i); printf(%d,p);int f(int a,int b) int c; if(ab) c=1; else if(a=b) c=0; e
14、lse c=-1; return(c);例例8-4 参数求值顺序(参数求值顺序(c7_4.c和和c7-5.c)#include main() int i=2,p; int f(int a,int b); p=f(i, i+); printf(%d,p);int f(int a,int b) int c; if(ab) c=1; else if(a=b) c=0; else c=-1; return(c);运行结果:运行结果:0运行结果:运行结果:1 (在在TC中中)8.4.2 函数调用的方式函数调用的方式u 函数语句:函数语句:例例printstar();printf(“Hello,World
15、!n”);u 函数表达式:函数表达式:例例m=max(a,b)*2;u 函数参数:函数参数:例例printf(“%d”,max(a,b);m=max(a,max(b,c);8.4.3 对被调用函数的声明和函数原型对被调用函数的声明和函数原型u对被调用函数要求:对被调用函数要求:必须是必须是已存在已存在的函数的函数库函数库函数: #include 用户自定义函数用户自定义函数: 主调函数对被调函数作主调函数对被调函数作函数函数声明声明u函数声明函数声明一般形式:一般形式:函数类型函数类型 函数名函数名(形参类型形参类型1形参名形参名1,. );或:或:函数类型函数类型 函数名函数名();(不提倡
16、使用)(不提倡使用)作用:告诉编译系统作用:告诉编译系统函数类型、参数个数及类型,以便检验函数类型、参数个数及类型,以便检验函数定义与函数声明不同函数定义与函数声明不同函数声明位置:函数声明位置:程序的数据说明部分(函数内或外)程序的数据说明部分(函数内或外)下列情况下,可不作函数声明下列情况下,可不作函数声明 若函数返值是若函数返值是char或或int型型,系统自动按,系统自动按int型处理型处理 被调用函数定义出现在主调函数之前被调用函数定义出现在主调函数之前 在所有的函数定义之前,在函数的外部已做了函数声明在所有的函数定义之前,在函数的外部已做了函数声明有些系统有些系统(如如Borlan
17、d C+)要求函数声明指出函数返回值类型和要求函数声明指出函数返回值类型和形参类型,并且对形参类型,并且对void 和和 int 型函数也要进行函数声明型函数也要进行函数声明float add(float x,float y)float z;z=x+y;return (z);void main (void)float a,b,c;scanf(“%f,%f”,&a,&b);c=add(a,b);printf(“%f”,c);char letter(char ,char);float f(float,float);int i(float,float);void main(void)char let
18、ter (char c1,char c2)float f(float x,float y)int i(flaot j,float k)#include float add(float x, float y) float z; z=x+y; return(z);main() float a,b,c; scanf(%f,%f,&a,&b); c=add(a,b); printf(sum is %f,c);被调函数出现在主调函数被调函数出现在主调函数之前,不必函数声明之前,不必函数声明/*c7_7.c*/#include main() int a,b; int c; scanf(%d,%d,&a,&
19、b); c=max(a,b); printf(Max is %dn,c);int max(int x,int y) int z; z=xy?x:y; return(z);int型函数可型函数可不作函数声明不作函数声明 Borland C+不行不行/*c7_6.c*/#include main() float add(float x,float y); /*函数声明函数声明*/ float a,b,c; scanf(%f,%f,&a,&b); c=add(a,b); printf(sum is %f,c);float add(float x, float y) float z; z=x+y; r
20、eturn(z);例例8.5 函数声明举例函数声明举例#include long sum(int a, int b);long factorial(int n);main() int 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+) rt
21、n*=i; return(rtn);long sum(int a,int b);long factorial(int n);文件包含编译预处理命令文件包含编译预处理命令函数声明函数声明函数定义函数定义函数调用函数调用函数调用函数调用函数返回值函数返回值形参形参实参实参8.5 函数的嵌套调用函数的嵌套调用嵌套调用嵌套调用C规定:函数规定:函数定义不可嵌套定义不可嵌套,但可以,但可以嵌套调用嵌套调用函数函数main( )调用函数调用函数a结束结束a函数函数b函数函数调用函数调用函数b例例 求三个数中最大数和最小数的差值求三个数中最大数和最小数的差值#include void main() int
22、a,b,c,d; int dif(int x,int y,int z); scanf(%d%d%d,&a,&b,&c); d=dif(a,b,c); printf(Max-Min=%dn,d); int dif(int x,int y,int z)int min(int x,int y,int z); int max(int x,int y,int z); return max(x,y,z)-min(x,y,z); int max(int x,int y,int z) int r; r=xy?x:y; return(rz?r:z); int min(int x,int y,int z) int
23、 r; r=xy?x:y; return(rz?r:z); main( )调用函数调用函数dif输出输出结束结束dif函数函数max函数函数调用函数调用函数max调用函数调用函数minmin函数函数例例8.6 用弦截法求方程根用弦截法求方程根08016523xxxxyf(x)0 x1x2xf(x1)f(x2)()()()(121221xfxfxfxxfxx求求f(x1)与与f(x2)连线与连线与x轴的交点轴的交点x输入输入x1,x2,求求f(x1),f(x2)直到直到f(x1)与与f(x2)异号异号y=f(x),y1=f(x1)y与与y1同号同号真真假假x1=xy1=yx2=x直到直到|y|
24、root=x 输出输出 rootroot函数函数main( )调用函数调用函数root输出根输出根 x结束结束root函数函数xpoint函数函数调用函数调用函数xpoint调用函数调用函数ff函数函数#include #include float f(float x) float y; y=(x-5.0)*x+16.0)*x-80.0; return(y);float xpoint(float x1,float x2) float y; y=(x1*f(x2)-x2*f(x1)/(f(x2)-f(x1); return(y);float root(float x1,float x2) flo
25、at x,y,y1; y1=f(x1); do x=xpoint(x1,x2); y=f(x); if(y*y10) y1=y; x1=x; else x2=x; while(fabs(y)=0.0001); return(x);main() float x1,x2,f1,f2,x; do printf(Input x1,x2:n); scanf(%f,%f,&x1,&x2); f1=f(x1); f2=f(x2); while(f1*f2=0); x=root(x1,x2); printf(A root of equation is %8.4f,x);运行情况:运行情况:Input x1,x
26、2:2,6 A root of equation is 5.00008.6 函数的递归调用函数的递归调用u定义:函数直接或间接的调用自身叫函数的递归调用定义:函数直接或间接的调用自身叫函数的递归调用f( )调调f调调f2调调f1f1( )f2( )u说明说明C编译系统对递归函数的自调用次数没有限制编译系统对递归函数的自调用次数没有限制每调用函数一次,在内存堆栈区分配空间,用于存每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出可能引起堆栈溢出int f(int x) int y,z; z=f(y)
27、; . 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);例例8.7: 5个人坐一起,问第个人坐一起,问第5个人多少岁?他说比第个人多少岁?他说比第4个人大个人大2岁。问第岁。问第4个人多个人多少岁?他说比第少岁?他说比第3个人大个人大2岁。问第岁。问第3个人多少岁?他说比第个人多少岁?他说比第2个人大个人大2岁。问第岁。问第1个人多少岁?他说个人多少岁?他说10岁。请问第岁。请问第5个人多大?个人多大?/*c7_8.c*/#includ
28、e int age (int n) int c; if(n=1) c=10; else c=age(n-1)+2; return(c);main() printf(%dn,age(5);age(5)=age(4)+2age(4 )=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10age(2)=12age(3)=14age(4)=16age(5)=18递递 归归 调调 用用递递 归归 返返 回回主函数主函数 1 2 3 4 3 2返回返回1 例例8.8 求求n的阶乘的阶乘) 1()!1() 1 , 0(1!nnnnn/*c7_9.c*/#includ
29、e int fac(int n) int f; if(n0) printf(n0,data error!); else if(n=0|n=1) f=1; else f=fac(n-1)*n; return(f);main() int n, y; printf(Input a integer number:); scanf(%d,&n); y=fac(n); printf(%d! =%15d,n,y);例例8.9 Hanoi问题问题#include void move(char getone, char putone) printf(%c-%cn,getone,putone); void han
30、oi(int n,char one,char two,char three) if(n=1) move(one,three); else hanoi(n-1,one,three,two); move(one,three); hanoi(n-1,two,one,three); main() int m; printf(Input the number of disks:); scanf(%d,&m); printf(The steps to moving %3d disks:n,m); hanoi(m,A,B,C);ABCa a和和b b为有为有1010个元素的整型数组个元素的整型数组比较两数组
31、对应元素比较两数组对应元素变量变量n,m,kn,m,k记录记录aibi,aiaibi,ai=bi,=bi,aibiaik,nk,认为数组认为数组abab 若若nk,nk,认为数组认为数组abab 若若n=k,n=k,认为数组认为数组a=ba=b8.7 数组作为函数参数数组作为函数参数1. 数组元素作函数实参数组元素作函数实参值传递值传递例例8.10 两个数组大小比较(两个数组大小比较(c7_10.c)4 43 32 21 10 05 5a a5656232312121010767688884 43 32 21 10 05 5b b212123234343989866665454n=0m=0k=
32、0in=0m=0k=1in=0m=1k=1in=1m=1k=1in=1m=1k=2in=2m=1k=2in=3m=1k=2#include main() int a10,b10,i,n=0,m=0,k=0; printf(Enter array a:n); for(i=0;i10;i+) scanf(%d,&ai); printf(Enter array b:n); for(i=0;i10;i+) scanf(%d,&bi); for(i=0;iy) flag=1; else if(xy) flag=-1; else flag=0; return(flag);float average(int
33、 array ,int n) int i; float aver,sum=array0; for(i=1;in;i+) sum=sum+arrayi; aver=sum/n; return(aver);main() float score_15=98.5,97,91.5,60,55; float score_210=67.5,89.5,69.5,99,77,89.5,76.5,54,60,99.5; printf(The average of class A is %6.2fn,average(score_1,5); printf(The average of class B is %6.2f
34、n,average(score_2,10);例例8.11 求学生的平均成绩求学生的平均成绩 #include float average(float array10); void main() float score10, ave; int i; printf(Input 10 scores: n); for( i=0; i10; i+ ) scanf(%d, &scorei); ave=average(score); printf(“n”); printf(Average is: %.2f, ave); float average(float array10) int i; float av
35、er,sum=0; for( i=0; i10; i+ ) sum+=arrayi; aver=sum/10; return aver; 实参用数组名实参用数组名形参用数组定义形参用数组定义 float array .2109score562312.88array另设一个参数,传递需处另设一个参数,传递需处理的数组元素个数的方法理的数组元素个数的方法2. 数组名作函数参数数组名作函数参数-地址传递地址传递u 地址传递地址传递方式:函数调用时,将数据的方式:函数调用时,将数据的存储地址存储地址作为参作为参数传递给形参数传递给形参特点:特点: 形参与实参占用形参与实参占用同样同样的存储单元的存储单
36、元 “双向双向”传递传递 实参和形参必须是实参和形参必须是地址地址常量或变量常量或变量u在主调函数与被调函数分别定义数组在主调函数与被调函数分别定义数组u实参数组与形参数组类型应一致实参数组与形参数组类型应一致u形参数组大小形参数组大小(多维数组第一维多维数组第一维)可不指定可不指定u形参数组名是形参数组名是地址变量。地址变量。用数组名作函数实参,不用数组名作函数实参,不是把数组的值传递给形参,而是把实参数组的起始是把数组的值传递给形参,而是把实参数组的起始地址传递给形参数组。地址传递给形参数组。例例 数组元素与数组名数组元素与数组名 作函数参数比较作函数参数比较12a调用前调用前a0a112
37、a调用调用a0a112xy21xy交换交换12a返回返回#include void swap2(int x,int y) int z; z=x; x=y; y=z;main() int a2=1,2; swap2(a0,a1); printf(a0=%dna1=%dn,a0,a1);数组元素作参数数组元素作参数:值传递值传递12a调用前调用前12ax调用调用21ax交换交换21a返回返回#include void swap2(int x ) int z; z=x0; x0=x1; x1=z;main() int a2=1,2; swap2(a); printf(a0=%dna1=%dn,a0,
38、a1);数组名作参数数组名作参数:地址传递地址传递例例 数组元素与数组名数组元素与数组名 作函数参数比较作函数参数比较例例8.13 数组排序数组排序-简单选择排序简单选择排序#include void sort( int array, int n) int i,j,k,t; for(i=0;in-1;i+) k=i; for(j=i+1;jn;j+) if(arrayjarrayk) k=j; if(k!=i) t=arrayi; arrayi=arrayk; arrayk=t; main() int a10,i; for(i=0;i10;i+) scanf(%d,&ai); sort(a,1
39、0); for(i=0;i10;i+) printf(%5d,ai); printf(n);0123456789a4968573299927137688arraykjjjkjkjjjjj949i=00123456789a4968573299927137688arraykjjkjjjjjj949i=1kkk1368例例8.13 数组排序数组排序-简单选择排序简单选择排序#include void sort( int array, int n) int i,j,k,t; for(i=0;in-1;i+) k=i; for(j=i+1;jn;j+) if(arrayjarrayk) k=j; if(
40、k!=i) t=arrayi; arrayi=arrayk; arrayk=t; main() int a10,i; for(i=0;i10;i+) scanf(%d,&ai); sort(a,10); for(i=0;i10;i+) printf(%5d,ai); printf(n);0123456789a49685732999271399888899array949i=81376273257494968kjk例例8.13 数组排序数组排序-简单选择排序简单选择排序#include void sort( int array, int n) int i,j,k,t; for(i=0;in-1;
41、i+) k=i; for(j=i+1;jn;j+) if(arrayjarrayk) k=j; if(k!=i) t=arrayi; arrayi=arrayk; arrayk=t; main() int a10,i; for(i=0;i10;i+) scanf(%d,&ai); sort(a,10); for(i=0;i10;i+) printf(%5d,ai); printf(n);例例8.14 求二维数组中最大元素值求二维数组中最大元素值j1 3 5 72 4 6 815173412imax=7j1 3 5 72 4 6 815173412imax=7j1 3 5 72 4 6 8151
42、73412imax=341 3 5 72 4 6 815173412ijmax=11 3 5 72 4 6 815173412ijmax=31 3 5 72 4 6 815173412ijmax=5#include int max_value ( int array34 ) int i,j,max; max=array00; for(i=0;i3;i+) for(j=0;jmax) max=arrayij; return(max);main() int a34=1,3,5,7, 2,4,6,8,15,17,34,12; printf(max value is %dn,max_value(a);
43、多维形参数组第一维维数多维形参数组第一维维数可省略可省略,第二维必须相同第二维必须相同 int array 48.8.1 局部变量局部变量局部变量也称为内部变量局部变量也称为内部变量u定义:在定义:在函数内函数内定义,定义,只在本函数内有效只在本函数内有效u说明:说明:main中定义的变量只在中定义的变量只在main中有效中有效不同函数中同名变量,占不同内存单元不同函数中同名变量,占不同内存单元 例例:不同函数中同名变量不同函数中同名变量形参属于局部变量形参属于局部变量可定义在复合语句中有效的变量可定义在复合语句中有效的变量 例:复合语句中变量例:复合语句中变量 #include main()
44、 int a,b; a=3; b=4; printf(main:a=%d,b=%dn,a,b); sub(); printf(main:a=%d,b=%dn,a,b);sub() int a,b; a=6; b=7; printf(sub:a=%d,b=%dn,a,b);运行结果:运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4运行结果:运行结果:5 4 3 2 1/*c7_11.c*/#include #define N 5main() int i; int aN=1,2,3,4,5; for(i=0;iN/2;i+) int temp; temp=ai; a
45、i=aN-i-1; aN-i-1=temp; for(i=0;iN;i+) printf(%d ,ai);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有效有效8.8.2 全局变量全局变量全局变量也称为外部变量全局变量也称为外部变量u定义:在定义:在函数外函数外定义,可为定义,可为本文件其他函数共用本文件其他函数共用u有效范围:从有效范围:从定义变量的位置开始定义变量的位置开始到本源文件结束。到本源文件结束。u说明:说明:设全局变量的作用增加了数据联
46、系的渠道设全局变量的作用增加了数据联系的渠道为区别局部与全局变量,习惯将全局变量的第一个字母大为区别局部与全局变量,习惯将全局变量的第一个字母大写写应尽量少使用全局变量,因为:应尽量少使用全局变量,因为: 全局变量在程序全部执行过程中占用存储单元全局变量在程序全部执行过程中占用存储单元 降低了函数的通用性、可靠性,可移植性降低了函数的通用性、可靠性,可移植性 降低程序清晰性,容易出错降低程序清晰性,容易出错若外部变量与局部变量同名,则外部变量被屏蔽若外部变量与局部变量同名,则外部变量被屏蔽int p=1,q=5;float f1(int a) int b,c; .int f3().char c
47、1,c2;char f2(int x,int y) int i,j; main() int m,n; .p,q作用范围作用范围c1,c2作用范围作用范围#include float Max,Min;float average(float array , int n) int i; float sum=array0; Max=Min=array0; for(i=1;iMax) Max=arrayi; else if(arrayiMin) Min=arrayi; sum+=arrayi; return(sum/n);main() int i; float ave,score10; /*Input
48、*/ ave=average(score,10); printf(Max=%6.2fnMin=%6.2fn average=%6.2fn,Max,Min,ave);作用域作用域MaxMin例例8.15 一个一维数组内放一个一维数组内放10个学生成绩,写一个函数,求个学生成绩,写一个函数,求出平均分,最高分和最低分。出平均分,最高分和最低分。/*ch8-16.c*/#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);例例8.16 外部变量与
49、局部变量同名外部变量与局部变量同名运行结果:运行结果:max=88.9.1 动态存储方式与静态存储方式动态存储方式与静态存储方式u 从变量存在的时间从变量存在的时间(生存期生存期)分动态与静态两种存储方式分动态与静态两种存储方式静态存储:程序运行期间分配固定存储空间静态存储:程序运行期间分配固定存储空间动态存储:程序运行期间根据需要动态分配存储空间动态存储:程序运行期间根据需要动态分配存储空间u 内存用户区内存用户区u 生存期生存期静态变量:静态变量: 从程序开始执行到程序结束从程序开始执行到程序结束动态变量:从包含该变量定义的函数开始执行至函数动态变量:从包含该变量定义的函数开始执行至函数执
50、行结束执行结束u 具体包含以下四种:具体包含以下四种:auto-自动型自动型 static-静态型静态型extern-外部型外部型 register-寄存器型寄存器型 程序区静态存储区动态存储区全局变量、局部静态变量形参变量局部动态变量(auto)函数调用现场保护和返回地址等(1) auto int x;(2) static int y;(3) register int i;(4) int z; extern z; 8.9.2 auto变量变量函数中的局部变量,如不做专门的说明,函数中的局部变量,如不做专门的说明,属于动态存储类,存储在动态存储区。这类变属于动态存储类,存储在动态存储区。这类变