第5章模块化编程_第1页
第5章模块化编程_第2页
第5章模块化编程_第3页
第5章模块化编程_第4页
第5章模块化编程_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

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

文档简介

1、模块化程序设计模块化程序设计n复杂问题的解决方法一般会是把原问题分解成若干个规模较小的问题加以解决,并可以类推的继续向下分解。n结构化程序设计的基本思想之一是程序的“模块化” (module)。所谓“模块化”就是把一个较为复杂的大程序化分成若干个功能相对独立的程序块,每个程序块实现一个功能。n在C语言中,这样的程序块被称为函数函数。n函数是程序的基本模块,C 语言被称为函数式语言。第五章第五章 模块化编程模块化编程d1d2垫圈面积垫圈面积=42122dd从一个例子说起:求从一个例子说起:求n个垫圈的面积总和个垫圈的面积总和E/求求n个垫圈的面积总和个垫圈的面积总和main()int n,i;f

2、loat t,d1,d2,sum=0;printf(垫圈的数量垫圈的数量=);scanf(%d,&n);for(i=1;i=n;i+)printf(%2d:外径外径=,i);scanf(%f,&d1);printf( 内径内径=,i);scanf(%f,&d2);t=(d1*d1-d2*d2)/4*3.1415926;sum+=t;printf(sum=%f,sum);getch();main() 输入垫圈个数输入垫圈个数n 调用求和函数调用求和函数sum(n) 显示显示n个垫圈面积个垫圈面积总和总和sum求求n数之和的函数数之和的函数float sum(int n)for(i=0;in;i+

3、) s+=area(d1,d2);求一个垫圈面积的函数求一个垫圈面积的函数float area(float d1,float d2)nd1 d2area反复反复n次次float sum(int n);float area(float d1,float d2);main()int n;printf(垫圈的数量垫圈的数量=);scanf(%d,&n);printf(sum=%f,sum(n);getch();float sum(int n) /计算计算n个垫圈面积之和的函数个垫圈面积之和的函数int i;float d1,d2,s=0;for(i=1;i=n;i+)printf(%2d:外径外径=

4、,i);scanf(%f,&d1);printf( 内径内径=,i);scanf(%f,&d2);s+=area(d1,d2);return s;float area(float d1,float d2) /计算一个垫圈面积的函数计算一个垫圈面积的函数float t;t=(d1*d1-d2*d2)/4*3.1415926;return t;垫圈的数量垫圈的数量=2 1:外径外径=2 内径内径=1 2:外径外径=3 内径内径=2 sum=6.283185在这个程序中我们使用了在这个程序中我们使用了3个函数。其中个函数。其中main()函数用于输入和输出,函数用于输入和输出,而计算求和以及垫圈面积

5、分别用独立的函数而计算求和以及垫圈面积分别用独立的函数sum()和和area()完成。完成。 几点体验:几点体验:函数sum,area要先声明,后使用;函数sum,area通过参数表中的参数n,d1,d2传递数据,以return语句从函数名sum,area获得返回的函数值。函数的参数n,d1,d2都是有类型的。函数参数的传递遵循NOT原则:Number、Order、Type必须一致必须一致几点体验:几点体验:The heart and soul of C programming is the function. A function represents a piece of code tha

6、t is a building block in the problem-solving process.Functions, called modules, allow programmers to modularize a program. Functions support structured programming and offer the following advantages:Hierarchical flow control;Break large tasks into smaller ones;Easy to maintain;Improve software reusa

7、bility.5.2 函数的定义与声明函数的定义与声明所有的函数定义,包括主函数main(),都是平行的,函数可以嵌套调用或相互调用,但不能嵌套定义。调用者称为主调函数,被调用的函数称为被调函数函数自己调用自己,称为递归调用。main 函数是主函数,它可以调用其它函数,而不允许被其它函数调用。程序的执行总是从main函数开始,完成对其它函数的调用后再返回到main函数,最后由main函数结束整个程序源程序中必须有,也只能有1个main函数/175.2.1 函数的分类函数的分类n从用户角度分类:从用户角度分类:n库函数: 由系统提供,用户无须定义,不必在程序中作类型说明,只需在程序前包含有该函数

8、原型的头文件即可在程序中直接调用。 如 printf()、scanf()、getchar()、putchar()n用户定义函数:由用户按需要写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用。 如例5.1中sum(int n)、area(float d1,float d2)n从函数执行过程分类从函数执行过程分类: 有返回值函数,无返回值函数n从函数定义形式分类从函数定义形式分类: 有参函数,无参函数/175.2.2 函数的定义形式函数的定义形式1. 无参函数的定义形式无参函数的定义形式 类型标识符类型标识符 函数名函数名(

9、) 声明部分声明部分 语句部分语句部分 类型标识符类型标识符:说明函数返回值的数据类型;若缺省,则为 int 类型;若函数无值,则定义为 voidvoid 类型函数名函数名:由用户自己命名,合法的标识符无参函数可以有也可以有返回值,但无返回值的较常见。无返回值函数的类型标识符是 void。void line() printf(n);/17【例【例5- 2】无返回值的无参函数举例】无返回值的无参函数举例#include #include void line() / 无参函数定义无参函数定义printf(n);main() printf( Hello !n); line(); / 无参函数调用无参

10、函数调用 printf( Follow me !n); line(); getch();/17Hello !Follow me !【例【例5- 3】有返回值的无参函数】有返回值的无参函数#include #include main() if(test() = 1) printf( return 1 n); else printf( return 0 n);int test() return 1; /17 return 12. 有参函数的定义形式有参函数的定义形式函数类型函数类型 函数名(形参类型说明表)函数名(形参类型说明表) 说明部分说明部分 语句部分语句部分 形参类型说明表形参类型说明表:

11、说明函数参数的个数和类型/17例例 正确的有参函数正确的有参函数 int max(int x,int y) int z; z=xy?x:y; return(z); 例例 错误的有参函数错误的有参函数 int max (int x, y) int z; z=xy?x:y; return(z); 5.2.3函数的参数和函数的返回值函数的参数和函数的返回值Formal parameters are parameters as they appear in function declarations.Actual parameters are parameters as they appear in

12、function calls.A parameter cannot be both a formal and an actual parameter, but both formal parameters and actual parameters can be either value parameters or variable parameters./171. 1. 函数的形参和实参函数的形参和实参n 在定义函数时,有参函数名后面括弧中的变量名称为形式参数(formal parameter),简称形参;n 在调用函数时,函数名后面括弧中的表达式称为实际参数(actual paramete

13、r),简称实参。n 主调函数和被调函数之间的信息交换可以通过实参与形参的结合和return语句来实现,称为按值调用(call by value)。例如 float max(float x,float y); main()float a,b,c,d,e;printf(a=);scanf(%f,&a);printf(b=);scanf(%f,&b);c=max(a,b); / 调用函数语句,调用函数语句,a,b为实参为实参printf(max is %fn,c);getch(); float max(float x,float y) /函数定义函数定义,x,y 为形参为形参float z;z=xy

14、?x:y;return z; 运行时输入:运行时输入:3.5 8.3显示:显示:max is 8.300000 通过函数调用,使通过函数调用,使main()和和max()这这两个函数中的数据发生联系两个函数中的数据发生联系形参与实参的特点:形参与实参的特点:形参形参只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后,则不能再使用该形参。实参实参可以是常量、变量、表达式、函数调用等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值、输入等方法使实参获得确定值。/1

15、7函数参数表的一致性原则(函数参数表的一致性原则(NOT)函数调用中实参的数目(Number)必须与函数原型中形参的数目一致。函数调用中实参的顺序(Order)必须与函数原型中形参的对应顺序一致。函数调用中实参的数据类型(Type)必须与函数原型中对应形参的数据类型一致。函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。在函数调用过程中,形参的值发生改变,而实参中的值不会变化。如果要将被调函数的结果返回主调函数,则应使用return语句并体现为主调函数名。/172. 函数函数的返回值的返回值/17n返回语句形式返回语句形式: return 表达式;

16、表达式;或或 return (表达式表达式);n功能:功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数。n说明:说明:n函数中可有多个return语句,但只执行第一个,n若无return语句,遇 时,自动返回调用函数,n若函数类型与return语句中表达式值的类型不一致,按函数类型为准,自动转换-函数调用转换函数调用转换n 语句语句 return 0; 结束main()程序运行,返回正常值0(把控制权交还给操作系统)对函数返回值说明:对函数返回值说明:int max(int x, int y) int z; z=(xy)?x:y; return z;/17或或int max

17、(int x, int y) return xy?x:y;这两种这两种return 写法等价写法等价1) 函数的值只能通过return语句返回主调函数。2)函数值的类型和函数定义中函数的类型应保持一致。如果两者不一致,则以函数的类型为准,编译系统会自动进行类型转换。3)若不要求被调函数有返回值,可以不使用return语句,或在return后面只有一个分号,即写成return;4)对于不返回函数值的函数,函数类型可以明确定义为“空类型”,即“void”。n函数的调用方式函数的调用方式n语句方式如:语句方式如:line(); 用于用于void型函数型函数n表达式方式如:表达式方式如:c=sum(a

18、,b);n参数方式如:参数方式如:m=max(c,max(a,b); n被调用的函数必须具备的条件被调用的函数必须具备的条件n被调用的函数必须是已经存在的函数n若调用库函数,应该在文件开头用#include命令将所需的信息包含到本文件中来。如:#include 或 #include math.hn 若使用自定义函数,该函数与主调函数应该在同一个文件中。n 一般应该在文件开头或主调函数中对被调函数进行说明。但有两个例外:n 整型或字符型函数可以不说明 n 被调函数写在主调函数之前可以不说明 总结:函数的调用方式和被调用的函数必须具备的条件总结:函数的调用方式和被调用的函数必须具备的条件 5.2.

19、4 函数的声明函数的声明n除int型或char型函数外,若主调用函数在被调用函数之前,必须在调用前用被调用函数的函数原型作声明n 函数声明(declaration)的方式采用函数原型(Function Prototype)n 函数原型一般形式为: 类型说明符类型说明符 被调函数名被调函数名(类型类型 形参,类型形参,类型 形参形参);或为: 类型说明符类型说明符 被调函数名被调函数名(类型,类型类型,类型); 例如: int max(int a,int b);也可以写为: int max(int,int);/17函数定义与函数声明的函数定义与函数声明的区别区别:函数定义是指对函数功能的建立,包

20、括指定函数名、函数类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。函数声明的作用是在程序的编译阶段对被调函数的合法性进行全面检查,将函数名、函数返回值的类型以及形参的类型、个数和顺序通知编译系统,以便在调用时系统进行对照检查。简而言之,函数的声明是将函数定义中的第1行(函数首部)复制后再加一个分号。/17可以省略函数可以省略函数声明的声明的几种情况几种情况被调函数的函数定义出现在主调函数之前,在主调函数中可以不对被调函数声明而直接调用,如例5-2。整型或字符型函数可以不加声明。系统将自动对被调函数返回值按整型处理,如例5-3。如果在文件的开头对函数统一进行了声明,则在各调用函数中

21、可不再对被调用函数加以声明。调用库函数时不必进行声明,只需用#include包含相应的头文件(标准库函数的原型在系统提供的相应头文件中)。/175.3 函数的调用函数的调用语言中,函数调用的一般形式为: 函数名函数名( (实际参数表实际参数表););函数调用的方式: 1)函数语句:函数调用的一般形式加上分号 即构成函数语句 例如: printf(%d,a); scanf(%d,&b); 2)函数表达式:函数调用作为表达式中的一项出现在表达式中,用函数返回值参与表达式的运算。这种方式要求函数是有返回值的。 例如: return xy?x:y; z=max(x,y)/17【例【例5- 4】求】求1

22、!+2!+10!long fact(int n)int i,t=1;for(i=1;i=n;i+)t*=i;return t;/17sum=4037913#include #includevoid main()long sum=0;int i;for(i=1;i=10;i+)sum+= fact(i); /函数表达式的调用函数表达式的调用printf(sum=%ld,sum);getch();函数调用的方式函数调用的方式 3) : 3)函数实参:函数调用作为另1个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的【例5- 5】函数调用作为另1个函

23、数调用的实际参数,求4个数的最大值#include #include int max(int x,int y); main()int a,b,c,d,e;printf(a=);scanf(%d,&a);printf(b=);scanf(%d,&b);printf(c=);scanf(%d,&c);printf(d=);scanf(%d,&d);e=max(max(max(a,b),c),d); /函数作为实参被调用函数作为实参被调用 printf(max is %dn,e);getch();int max(int x,int y)return xy?x:y;/175.3.2 函数调用时的参数传

24、递函数调用时的参数传递主调函数把实参值复制给被调函数形参的过程,称为参数传递参数传递参数传递方式:参数传递方式:n如果使用普通变量作为函数的参数进行调用,这种方式称为按值调用按值调用(Call by Value)。n如果使用地址型数据作为函数参数进行调用,则称为按地址调用按地址调用(Call by Reference)。We have seen call-by-reference when we use the scanf() function. Values supplied by the calling function as parameters cannot be updated by

25、 the called function. When we want a called function to update an identifier in the calling function, we pass it a pointer to the identifier. The effect of call-by-reference is accomplished by:a.Declaring a function parameter to be a pointer.b.Using the dereferenced pointer in the function body.c.Pa

26、ssing an address as an argument when the function is called./171. 按值调用(按值调用(Call by Value)1) 变量作为函数参数变量作为函数参数n 当形参和实参是基本型变量时,参数传递的方式是按值调用(Call by Value),形参和实参各自占用不同的存储单元。因此,函数中形参的数值变化不会导致实参的相应变化。函数只能通过return语句返回1个函数值n 按值调用采用的就是一种“单向单向”的值传递方式。写程序,使用swap函数来尝试交换两个数值x和yswap(int a,int b) int t;t=a, a=b,

27、b=t;return a; return b; 你的程序交换成功了吗?/17main() int x=7,y=11; swap(x,y); printf(%d %dn,x,y); getch();2)数组元素作函数实参数组元素作函数实参 数组是一种构造类型,其中数组元素的使用等同于基本型变量,因此数组元素作函数实参时,实参和形参间也是“单向”值传递。而函数的形参仍然用基本型变量,当函数调用时,把作为实参的数组元素的值传送给形参变量,从而实现单向的值传递。【例5-7】的程序段: int a5,i; printf(input 5 numbersn); for(i=0;i5;i+) scanf(%d

28、,&ai); nzp(ai); /172 .按地址调用(按地址调用(Call by Reference)当形参和实参是地址变量、指针变量或者数组名时,实参到形参的当形参和实参是地址变量、指针变量或者数组名时,实参到形参的参数传递是地址值的传递,称为按地址调用(参数传递是地址值的传递,称为按地址调用(Call by Reference)。按地址调用采用的就是一种按地址调用采用的就是一种“双向双向”的地址传递方式。形参和实参的地址传递方式。形参和实参此时此时指向同一存储单元,函数中形参的数值变化直接导致了实参的指向同一存储单元,函数中形参的数值变化直接导致了实参的相应变化,函数也可以无须通过相应变

29、化,函数也可以无须通过return语句返回函数值了。语句返回函数值了。 1)指针作函数形参指针作函数形参 指针作函数形参时,表示形参接收的数据只能是一个地址值。 写一个新的swap()函数来尝试交换x,y的值: swap(int *a, int *b) int t; t=*a, *a=*b, *b=t; /17【例【例5- 8】用指针作函数参数实现两个数的交换。】用指针作函数参数实现两个数的交换。main()int x=7,y=11; printf(%d %dn,x,y); swap(&x,&y); printf(%d %dn,x,y);getch();/17实参实参&x形参指针形参指针a&x

30、x7*a*b形参指形参指针针b&y实参实参&yy11t随机随机数数swap()main()(调用调用swap函数函数t随机随机数数swap()main()实参实参&x形参指形参指针针a&xx11*a*b形参指形参指针针b&y实参实参&yy7(执行执行swap函数函数2 ) 数组名作为函数参数数组名作为函数参数n用不带方括号的数组名作为实参调用函数,可以把一个数组传递给一个函数 。n用数组名作实参实际上是将数组的首地址传给被调函数,使形参数组与实参数组具有相同的首地址,实际占用同一段存储单元。/17主调函数主调函数被调函数被调函数地址值地址值修改修改地址值地址值地址值地址值数组数组地址值地址值地

31、址值地址值已改变已改变实参实参形参形参实参实参实参实参形参形参(函数调用时函数调用时 执行被调函数执行被调函数 返回主调函数返回主调函数【例例5- 9】用数组名作函数参数实现数组元素平均值的求解】用数组名作函数参数实现数组元素平均值的求解/数组数组a中存放了中存放了1个学生个学生5门课程的成绩,求平均成绩。门课程的成绩,求平均成绩。float aver(float a) int i; float avr,s=a0; for(i=1;i5;i+) s=s+ai; avr=s/5; return avr;main() float sco5,avr; int i; printf(ninput 5 s

32、cores:n); for(i=0;i5;i+) scanf(%f,&scoi); avr=aver(sco); printf(average score is %5.2f,avr); getch();input 5 scores:89 88 76 90 92 average score is 87.00使用使用数组名作为函数参数时还应注意以下问题:数组名作为函数参数时还应注意以下问题:n形参数组和实参数组的类型必须一致,否则将引起错误。n因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,虽不至于出现语法错误(编译能通过),但程序执行结果将与实际不符。n在函

33、数中为了防止对形参数组的赋值,可以在该形参数组声明中加限定词const。/17/数组求和数组求和 c=a+bvoid add(const int a,const int b,int c,int n)int i;for(i=0;in;+i)ci=ai+bi;main()int i,x5=1,3,5,7,9,y5=10,8,6,4,2,z5;add(x,y,z,5);for(i=0;i5;i+) printf(%4d,zi); getch();语言中不允许作嵌套的函数定义。但是语言允许在语言中不允许作嵌套的函数定义。但是语言允许在1个个函数的定义中出现对另函数的定义中出现对另1个函数的调用。这样就

34、出现了函数个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。的嵌套调用。即在被调函数中又调用其它函数。【例例5-12】sum=1!+2!+3!+10!。!。 main()函数 + sum()函数 + fact()函数 /175.3.3函数的嵌套调用函数的嵌套调用main()函数函数sum()函数函数fact()函数函数调用调用sum函数函数调用调用fact函数函数main()结束结束sum()结束结束fact()结束结束float sum(int n) int a; float s=0; for (a=1;a=n;a+) s+=fac(a); return s; floa

35、t sum(int n);float fac(int a);main ( ) float x; x=sum(10); printf(“x=%10.1f,x); getch(); float fac(int a) float t=1; int n=1; while (n06/2=303/2=101/2=0 0显示余数1回回溯溯过过程程显示余数1显示余数0显示余数0 递递 推推 过过程程【例例5- 13】用递归法实现用递归法实现1个正整数以二进制数形式的输出个正整数以二进制数形式的输出 main() bin(12); /运行结果:运行结果:1100 getch();bin(int x) if(x/

36、20) bin(x/2); / 短除短除2直到商为直到商为0 printf(%d ,x%2);/ (逐层逐层)显示余数显示余数图解执行过程图解执行过程main() bin(12); getch();bin(12) if(12/20) bin(12/2); printf(%d ,12%2);bin(6) if(6/20) bin(6/2); printf(%d ,6%2);bin(3) if(3/20) bin( 3/2); printf(%d ,3%2);bin(1) if(1/20) bin(1/2); printf(%d ,1%2); 1 (n=0) n由于由于 n!= n(n-1)! (

37、n0)根据阶乘的定义,可将根据阶乘的定义,可将递归关系用下述公式表示:递归关系用下述公式表示: f(0)= 1; f(n)= n*f(n-1);相应的程序语句为:相应的程序语句为: if(n=0)x=1;elsex=n*f(n-1);而而 : n!=n*(n-1)! (n-1)!=(n-1)*(n-2)! (n-2)!=(n-2)*(n-3)! 2!=2*1! 1!=1*0! 0!=1 (初始条件) 构成了回溯过程构成了回溯过程【例例5- 14】用递归法计算用递归法计算n!求求n! n!的递归程序的递归程序 #include #include main() long fact(int); in

38、t n; printf(ninput n: ); scanf(%d,&n); printf(%d!=%ldn,n,fact(n);getch();long fact(int n) if(n0) return n*fact(n-1); else return 1;结果:结果:5!=120 1 (n=0) n!= n(n-1)! (n0)运行过程:运行过程:/17main() fact(5) fact(5) 5*fact(4) fact(4) 4*fact(3) fact(3) 3*fact(2) fact(2) 2*fact(1) fact(1) 1*fact(0) fact(0) 1 fact

39、(3) 3*fact(2) 1126241205.4 变量的作用域与存储类型变量的作用域与存储类型5.4.1. 变量的作用域 变量有效性的范围称变量的作用域 函数外部定义的,称为全局变量Global variable; 函数内部定义的,称为局部变量Local variable。1) 局部变量 凡在块内部或者函数内部定义的变量称为局部变量。局部变量是在块内或者函数内作定义说明的,其作用域仅限于所在的块或者函数内,在变量的作用域以外该变量不能被引用。/17【例例5- 16】函数内定义的局部变量与复合语句中定义的局部变函数内定义的局部变量与复合语句中定义的局部变量量 /17#include #inc

40、lude main()int x=10;printf(x=%dn,x);if(x0)int x;x=-10;printf(x=%dn,x);printf(x=%dn,x);getch();函数内局部变量函数内局部变量X=10 有效有效复合语句内局部变量复合语句内局部变量X=-10 有效有效函数内局部变量函数内局部变量X=10 有效有效局部变量作用域的几点说明局部变量作用域的几点说明主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是1个函数,它与其它函数是平行关系。这一点是与其它语言不同的,应予以注意。形参变量是属于被调函数

41、的局部变量,实参变量是属于主调函数的局部变量。允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。/172)全局变量)全局变量凡在函数外部定义的变量称为全局变量(或称为外部变量),其作用域从定义位置开始到本源文件结束。n在函数中使用全局变量,一般应作全局变量说明。n若是在程序最开始定义的全局变量,则变量可以在整个程序各个函数中使用;若是在程序中其他位置定义的全局变量,则变量可以在从定义位置以后的各函数中使用。/17【例【例5- 17】用全局变量实现两个数的交换。】用全局变量实现两个数的交换。#include #include int x,y; /

42、全局变量全局变量x、y默认初值为默认初值为0void swap()x=y=x=y; /使用异或运算实现两个整数交换使用异或运算实现两个整数交换main()x=3,y=7;swap();printf(x=%d y=%dn,x,y);getch();【例例5- 18】用用全局变量将函数中多个数据返回到主函数全局变量将函数中多个数据返回到主函数/ 输入立方体的长宽高输入立方体的长宽高l,w,h。求体积及。求体积及3个面个面x*y,x*z,y*z的面积。的面积。#include #include int s1,s2,s3; / 3个全局变量分别表示立方体的个全局变量分别表示立方体的3个面积个面积int

43、 vs( int a,int b,int c) int v; / 局部变量表示立方体的体积局部变量表示立方体的体积 v=a*b*c; s1=a*b; s2=b*c; s3=a*c; return v; / 立方体的体积通过函数的返回值传回主调函数立方体的体积通过函数的返回值传回主调函数main() int v,l,w,h; printf(ninput length,width and heightn); scanf(%d%d%d,&l,&w,&h); v=vs(l,w,h); printf(nv=%d,s1=%d,s2=%d,s3=%dn,v,s1,s2,s3); getch();关于全局变量

44、的说明:关于全局变量的说明:如果没有指定初值,则全局变量的初值是变量数据类型的系统默认值。int类型为0,float类型为0.0,char类型为0,指针类型为NULL。定义的全局变量在某一函数中发生改变,则该变量的值将影响到其它函数。可以利用全局变量从被调函数中返回多个值。若函数中的局部变量与全局变量同名,则在该函数中全局变量不起作用。过多的使用全局变量不仅加大了系统开销,而且使程序的可读性降低。因此,要限制使用全局变量。若要在全局变量定义之前使用全局变量,可在使用前使用extern进行声明。/175.4.2 变量的存储类型变量的存储类型1)静态存储方式与动态存储方式用户存储空间可以分为3个部

45、分:存储在静态存储区中的变量叫做静态变量,如全局变量。存储在动态存储区中的变量叫做动态变量。如函数形参、局部变量、函数调用时的现场保护和返回地址等Every variable and function in C has two attributes: type and storage class. The four storage classes are: auto,extern,register, static. By far the most common storage class for variables is automatic. However, the programmer n

46、eeds to know about all the storage class. They all have important uses./172)变量的存储类别)变量的存储类别在C语言中,每个变量都有两个属性:数据类型和数据的存储类别。对1个变量的完整定义应指出变量的两种属性,因此变量类型定义的一般形式为: 存储类别符存储类别符 数据类型符数据类型符 变量表变量表;n变量的存储类别分为:auto(自动类别)、register(寄存器类别)、static(静态类别)和extern(外部类别)4种。 (1) auto 变量变量 函数中的局部变量,如果没有专门声明,都是动态分配存储空间的,数据

47、存储在动态存储区中。这类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明。变量存贮类别的默认值是 auto。变量定义时自动赋给随机数。/17(2)用用static声明局部变量声明局部变量 有时希望函数中的局部变量在函数调用结束后不消失且保留原值,当下次再调用该函数时还能继续使用这些变量,这时就应该指定这些局部变量为“静态局部变量”,用关键字static进行声明。(3) register变量变量 为了提高效率,C语言允许将局部变量的值放在CPU中的寄存器中,这种变量叫“寄存器变量”,用关键字register进行声明。 (4)用用extern声明外部变量声明外部变量 外部变量(即全局

48、变量)是在函数的外部定义的,外部变量的作用域是从定义开始到源文件的结束。为了扩大外部变量的作用域,系统允许用extern来声明外部变量,表示该变量是1个已经定义的外部变量。 /17【例【例5- 22】用】用extern声明外部变量,扩展程序文件中的作用域声明外部变量,扩展程序文件中的作用域#include #include int max(int x,int y) int z; z=xy?x:y; return(z);main() extern A,B; / 等同于等同于extern int A,B;,是外部变量的声明,是外部变量的声明 printf(%dn,max(A,B); getch()

49、;int A=13,B=-8; /外部变量(全局变量)的定外部变量(全局变量)的定义义/175.5 内部函数与外部函数内部函数与外部函数内部函数:函数只能在所定义的源文件中被其他函数调用,而不能被程序中其他源文件中的函数所调用声明方式: static类型定义符函数名类型定义符函数名 (参数表参数表);外部函数: 函数除可以被所定义的源文件中的其他函数调用外,还可以被程序中其他源文件中的函数所调用声明方式: extern类型定义符函数名类型定义符函数名 (参数表参数表)/175.6 指针函数指针函数在C语言中,函数的返回值的类型可以是指针,即返回值为某种数据类型的地址。返回指针的函数称为指针函数

50、。指针函数的定义格式: 类型定义符类型定义符 *函数名函数名(形式参数表形式参数表) 函数体函数体 例如:例如: char *day(int n)/17【例【例5- 24】由键盘输入表示星期日至星期六的】由键盘输入表示星期日至星期六的0 6,显示出其英文名,显示出其英文名,若不是若不是0 6则显示则显示“Illegal day”。#include #include char *day(int n)char *name8= Sunday , Monday , Tuesday , Wednesday , Thursday ,Friday , Saturday , Illegal day ; if(n6) return(name7); else return(namen);main() int x; scanf(d, &x); printf(s n, day(x); getch();程序中name是1个指针数组,它的每

温馨提示

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

评论

0/150

提交评论