收藏 分享(赏)

C语言程序设计 第七章函数.ppt

上传人:dzzj200808 文档编号:3655250 上传时间:2018-11-15 格式:PPT 页数:84 大小:1.06MB
下载 相关 举报
C语言程序设计 第七章函数.ppt_第1页
第1页 / 共84页
C语言程序设计 第七章函数.ppt_第2页
第2页 / 共84页
C语言程序设计 第七章函数.ppt_第3页
第3页 / 共84页
C语言程序设计 第七章函数.ppt_第4页
第4页 / 共84页
C语言程序设计 第七章函数.ppt_第5页
第5页 / 共84页
点击查看更多>>
资源描述

1、第7章 函 数,模块化程序设计 基本思想:将大的程序按功能分割成一些小模块, 特点: 各模块相对独立、功能单一、结构清晰简单 控制了程序设计的复杂性 每个模块简单,所以可靠性高 避免程序开发的重复劳动,缩短开发周期 易于维护和功能扩充 开发方法: 自上向下,逐步分解,分而治之,是面向过程程序设计语言的核心,第7章 函数,7.1.1 C程序的结构,C程序基本结构,C程序,可由一个或多个源程序文件组成;每个源程序文件又由若干函数构成;但整个程序有且仅有一个主函数;程序运行时从main函数开始执行,main函数可调用其它函数,最终一律返回到main函数结束运行。 除main函数外,其它函数可相互调用

2、; 函数不可嵌套定义,具有全局性、平行性; 函数分为有参与无参函数,有返回值和无返回值函数,主调和被调函数,C程序特点:,函数的分类,按照函数定义的角度分为:,1.标准库函数:,是由系统定义地,也不必在程序中进行类型说 明,要调用某个库函数,则要用预处理命令 #include将该函数所在的头文件包含到程序中。,使用库函数应注意:,1、函数功能,2、函数参数的数目和顺序,及各参数意义和类型,3、函数返回值意义和类型,4、需要使用的包含文件,2.用户自定义的函数,按照函数的参数传递形式分为:,无参函数,有参函数,按照函数的返回值类型分为:,有返回值,无返回值,按照函数的使用范围分为:,内部函数,外

3、部函数,按函数的定义形式和使用范围的分类:,8.2 函数的定义,-无参函数的定义,类型名 函数名( ) 声明部分执行部分,说明: 类型名为函数返回值类型, 如果定义时未指定,系统默认为int型; 无返回值的函数的类型名应为void。 函数名须是合法标识符,不能与其他函数或变量重名,#include void printstar() printf(“*n“); void print_message() printf(“How are you!n“); main() printstar();print_message();printstar(); ,类型标识符 函数名( 形参表列 ) 声明部分执行

4、部分,形参表列必须声明形参的类型,函数的定义,-有参函数的定义,形参类型说明表,一般格式为: 数据类型1 形参1, , 数据类型n 形参n,#include float average(float x,float y,float z) float aver; aver=(x+y+z)/3;return(aver); main() float a,b,c,ave;a=6.5; b=4.2; c=25.3;ave=average(a,b,c); printf(“average=%f”,ave); ,void 函数名( ) ,函数体可以没有, 表示占个位置, 实现功能以后补写。,函数的定义,-空函数

5、的定义,/*求最大值*/ void max( int x) /* 求最大值*/ ,空函数的应用,main() int a10=.;/* 求最大值*/int m_max=max(a);printf(“m_max=%d”,m_max); ,函数的调用:1、主调函数与被调函数main函数是整个程序的执行入口 程序的执行是从main函数开始的 一般函数必须由main函数(或其它函数)调用才能执行。,函数调用关系示意图,2、函数参数和函数的值,函数参数分为:实际参数和形式参数,在函数定义的函数首部, 函数名后的括号中说明的 变量,简称形参。形参的个数可以有多个,多个形参 之间用逗号隔开。,形式参数:,实

6、际参数:,函数被调用时, 在调用处给出对应的参数,简称实参, 实参往往是具有明确值的常量、变量或表达式等。,#include float average(float x,float y,float z) float aver; aver=(x+y+z)/3;return(aver); main() float a,b,c,ave;a=6.5; b=4.2; c=25.3;ave=average(a,b,c); printf(“average=%f”,ave); ,形式参数(形参),实际参数(实参),注意:,1.形参在未出现函数调用时,他们并不占内存,只有发生函数调用时才会被分配空间,而且在该函

7、数结束后,它所占的所有内存也被释放;,2.实参必须是具有确定值的常量,变量或表达式;,3.形参必须在定义时就声明其类型;,6.实参与形参的类型应相同或赋值兼容;,7.C语言规定,实参与形参之间必须是单向的值传递。,4.实参的个数和形参的个数应该相等;,5.实参与形参在顺序上应该一一对应;,参数的结合问题:在函数调用时,将实参值传给对应的形参,例如: 编一程序,将主函数中的两个变量的 值传递给swap函数中的两个形参,交换两个 形参的值。,#include void swap(int x, int y) int z;z=x; x=y; y=z; printf(“nx=%d,y=%d“,x ,y)

8、; main( ) int a= 10,b=20;swap(a,b); printf(“na=%d,b=%dn“,a,b); ,形式参数(形参),实际参数(实参),单向值传递,例如: 编一程序,将主函数中的两个变量的 值传递给swap函数中的两个形参,交换两个 形参的值。,#include void swap(int x, int y) int z;z=x; x=y; y=z; printf(“nx=%d,y=%d“,x ,y); main( ) int a= 10,b=20;swap(a,b); printf(“na=%d,b=%dn“,a,b); ,程序输出结果: x=20,y=10 a=

9、10,b=20,main,swap,20,b,10,a,z,10,y,20,x,10,10,20,交换失败,例 计算x的立方,#include float cube(float x) return(x*x*x); main() float a, product;printf(“Please input value of a:“);scanf(“%f“, ,x,1.2,1.2,1.728,函数的值,即函数的返回值,是通过函数中的return语句获得的.,return语句的一般形式:,return (表达式);,return 表达式 ;,执行过程:,执行return语句后,如果该表达式的类型 与函

10、数首部中定义的函数类型一致,则直 接将结果返回主调函数;否则,系统自动将 结果的类型转换成定义的函数类型。,无返回值的函数如果被调用函数中没有return语句,函数带回的是一个不确定的值。为了明确表示“不带回值”,可以用“void”定义“无类型”(或称“空类型”)。这样,系统就保证不使函数带回任何值,即禁止在调用函数中使用被调用函数的返回值。为使程序减少出错,凡不要求带回函数值的函数,一般应定义为“void“类型。 printstar( ) printf(“*n“); ,void swap(int x,int y ) int temp;temp=x; x=y; y=temp;,通过 retur

11、n 语句只能返回一个数值。 函数内可有多条返回语句,但每条返回语句的返回值只有一个。 当函数不需指明返回值时,可以写成:return ; 当函数中无返回语句时,表示最后一条语句执行完后遇 自动返回。,说明:,函数的调用,函数调用是使函数进行一次实际的执行。,格式:,函数名(实际参数表),说明 实参在调用时必须有确定的值,可以是常量、变量和表达式。 函数的实参和形参应在个数、类型和顺序上一一对应,否则会发生类型不匹配的错误。 对于无参函数,调用时实参表列为空,但( )不能省 。,按函数在程序中出现的位置有以下3种函数调用方式:,函数调用的方式,1.函数语句调用 把函数调用作为一个语句 不要求函数

12、带回明确的返回值 只完成一定的操作,#include void printstar() printf(“*n“); void print_message() printf(“How are you!n“); main() printstar();print_message();printstar(); ,2.函数表达式调用 以表达式形式出现在程序中 要求函数必须带回确定的返回值,c=2*max(a,b);,3.函数参数调用 作为参数出现在程序中 要求函数必须带回确定的返回值,m=max(a,max(b,c);,函数的调用过程,1. 根据函数名找到被调函数, 若没找到, 系统将 报告出错信息;

13、若找到, 为形参开辟存储空间; 2. 计算实参的值。将实参的值传递给形参; 3. 保护主调函数的现场, 中断主调函数, 转到被调函数的函数体中开始执行;,4. 遇到return语句或函数结束的花括号时, 返回 主调函数; 5. 释放形参和调用函数中临时变量的内存空间; 6. 恢复现场从主调函数的中断处继续执行。,函数 开始 调用,函数 结束 调用,#include float average(float x,float y,float z) float aver; aver=(x+y+z)/3;return(aver); main() float a,b,c,ave;a=6.5; b=4.2;

14、 c=25.3;ave=average(a,b,c); printf(“average=%f”,ave); ,main,average,12.0,ave,25.3,c,4.2,b,6.5,a,aver,12.0,z,25.3,y,4.2,x,6.5,函数之间的位置关系,在一个程序中有多个函数,那么, 各函数之间的前后位置关系规定如下:,1、被调函数在前面,主调函数在后面.即先定义后调用。,2、主调函数在前面,被调函数在后面。这时,必须在调用的语句之前,对被调用的函数进行原型声明(说明),可在主调函数的说明部分,也可在程序的开始处的说明部分进行。 3、被调函数是库函数或另一文件中的自定义函数,

15、则在本程序文件的起始部分用 #include 命令将对应的文件包含到本文件中来。,int add(int x,int y) return(x+y); main() int a=10,b=24,sum;printf(“input a,b:“);sum=add(a, b);printf(”sum= %dn“,sum); ,main() int a=10,b=24,sum;printf(“input a,b:“);sum=add(a, b);printf(”sum= %dn“,sum); int add(int x,int y) return(x+y); ,int add(int x,int y);

16、,int add(int x,int y);,函数原型声明方法常用的是: 用函数定义中的函数首部, 再加上一个分号; 也可以省略函数首部中的形参名, 但必须保留形参的类型。 long fac(int x); /* 对除main之外的所有自定义函数进行原型说明 */ int cmn(int m,int n); main() /*main函数*/ int m,n,c; long fac(int x) /*fac函数*/ int cmn(int m,int n); /*cmn函数*/ ,/*也可以写成long fac(int);*/,/*也可以写成int cmn(int,int);*/,例: lon

17、g fac(int x); /* 函数原型说明 */main() int m,n,c;printf(“input m,n:“);scanf(“%d%d“,数组作为函数参数,数组元素作函数实参一维数组名作函数参数多维数组名作函数参数,例:计算数组中相邻两元素之间的差值。,数组元素作函数实参值传递,int dif(int x,int y) return x-y; main() int i, a4=0,1,2,3;for(i=0;i3;i+) printf(“the diff between %d and %d is “,i,i+1);printf(“%dn“, dif(ai,ai+1) ); ,t

18、he diff between 0 and 1 is -1 the diff between 1 and 2 is -1 the diff between 2 and 3 is -1,数组名作函数参数地址传递,在主调函数与被调函数分别定义数组,且类型应一致。 形参数组大小(多维数组第一维)可不指定,但 不能省。编译程序并不为形参数组分配空间。 数组名表示数组在内存中的起始地址。,例:从键盘输入8学生的成绩,编写函数使用简 单选择排序将成绩由高到低排序,并输出成绩。,#define N 10 void SelectSort(int a , int n); void InputArray(int

19、a , int n); void OutputArray(int a , int n); main() int n=8,scoreN;InputArray(score,n);SelectSort(score,n);OutputArray(score,n); ,void InputArray(int a,int n) int i;printf(“Input %d scores:n“,n);for(i=0;in;i+) scanf(“%d“, ,void OutputArray(int a,int n) int i;printf(“The sorted scores:n“);for(i=0;in;

20、i+) printf(“%4d“,ai); ,void SelectSort(int a , int n) int i,j,k,t;for(i=0;in-1;i+) k=i;for(j=i+1;jn;j+) if(akaj)k=j;if(k!=i) t=ai; ai=ak; ak=t; ,用数组名作函数参数,应该在主调函数和被调函数分别定义数组,不能只在一方定义; 实参数组与形参数组类型应一致; 形参数组也可以不指定大小,在定义数组时在数组名后面跟一个 ;为了在被调用函数中处理数组元素的需要,将数组个数作为一个参数; 用数组名作函数实参时,不是把数组的值传递给形参,而是把实参数组的起始地址传递

21、给形参数组,这样两个数组就共占同一段内存单元。,说明:,例:求数组中所有元素的最大值。,int getmax( int b34 ) /*或 int getmax(int b 4)*/ int i, j , max=b00;for(i=0; i3; i+); for(j=0; j4; j+)if(max bij) max=bij;return max; main() int a34, i, j;printf(“nEnter 6 integers:“);for(i=0;i3;i+)for(j=0;j4;j+)scanf(“%d“, ,7.6函数的嵌套与递归7.4.1 函数的嵌套调用C语言的函数定义

22、都是互相平行、独立的,也就是说在定义函数时,一个函数内不能包含另一个函数。 但可嵌套调用函数,即在主调函数调用被调函数的过程中,被调函数又调用了另一被调函数。,图示的是两层嵌套(连main函数共3层函数),其执行过程是: 执行main函数的开头部分; 遇函数调用a的操作语句,流程转去a函数; 执行a函数的开头部分; 遇调用b函数的操作语句,流程转去函数b; 执行b函数,如果再无其它嵌套函数,则完成b函数的全部操作; 返回调用b函数处,即返回a函数; 继续执行a函数中尚未执行的部分,直到a函数结束; 返回main函数中调用a函数处; 继续执行main函数的剩余部分直到结束。,例:求三个数中最大数

23、和最小数的差值。,int dif(int x,int y,int z) return max(x,y,z)-min(x,y,z); main() int a,b,c,d;scanf(“%d%d%d“, ,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 r;r=xy?x:y;return(rz?r:z); ,例:求圆环的面积。,#include #define PI 3.1415926 float area_ring(float x,float y); float a

24、rea(float r); main() float r,r1; printf(“input tow figure:n”);scanf(“%f%f”, ,float area_ring(float x,float y) float c;c=fabs(area(x)-area(y);return(c); float area(float r) return(PI*r*r); ,函数的递归调用,在函数的执行过程中又直接或间接调用该函数本身 直接递归调用在函数中直接调用函数本身 间接递归调用在函数中调用其它函数,其它函数又调用原函数,int f(int x) int y,z;z=f(y);.retu

25、rn(2*z); ,C编译系统对递归函数的自调用次数没有限制。,例:计算n!。,分析: 求解n的阶乘实际上有两种方法, 一种是连乘法,它基于阶乘定义公式:n!=1*2*3*n,实现方法是用循环完成。,另一种方法基于阶乘递归定义公式:,用函数的直接递归调用实现,main( ) int n; long y;printf(“ninput a integer number:n“);scanf(“%d“, ,long fac (int n) long f;if(n=0) f=1;else f=n*fac (n-1); return(f); ,main(),n=1,n=2,n=3,n=4,f=24,f=6

26、,f=2,f=1,f=4*fac(3),f=3*fac(2),f=2*fac(1),f=1,fac(4),注意:在递归调用过程中,不同层的同名局部变量是不同的变成机器代码后, 执行时相当于将其拉成直线 (线性程序代码)。,第一次调用fac,第二次调用fac,第三次调用fac,第四次调用fac,long fac(int n) return(n=1) ? 1 : fac(n-1)*n ); ,long fac(int n) long f; if(n=1) f=1;else f=fac(n-1)*n;return( f ); ,main() int n; long y;printf(“ninput

27、an integer number:n“);scanf(“%d“,long fac(2) long f; if(2=1) f=1;else f=fac(2-1)*2;long fac(1) long f; if(1=1) f=1;else f=fac(n-1)*n;return( 1); return( 2); return( 6 ); return( 24 ); printf(“%d!=%ld“,n,y);,例:Hanoi塔问题。,一块板上有三根杆, a, b, c。a杆上套有64个 圆盘, 大的在下,小的在上。要把这64个圆盘 从a杆移动c杆上,每次只能移动一个圆盘, b 杆可以暂时存放。

28、但在任何时候,任何杆上 的圆盘都必须保持大盘在下, 小盘在上。,将A塔上的红、黄两盘移动到B上蓝盘放到C上将红、黄两盘从B移动到C盘上。(完成),问题分析:,n=1时,直接将其从A-C ; n1时, 只要先将前n-1个借助C从A-B, 那么可以把第n个直接从A-C; 将剩下的n-1个借助A从B-C,,问题性质相同,因此适合采用递归过程!,递归结束条件,问题分解,设将n个盘从a借助b移到c杆的算法为 move(n,a,b,c),则:移动盘子算法如下:,把a上面的n-1个盘借助c移到b,记做move(n-1,a,c,b);,把最下面的1个盘从a直接移到c;,把b上的n-1个盘借助a移到c,记做mo

29、ve(n-1,b,a,c);,显然这是一个递归算法,按此算法编程如下:,main( ) int m;printf(“nInput number:“); scanf(“%d“, ,void move(int n,int x,int y,int z) if(n=1) printf(“%c-%cn“,x,z);else move(n-1,x,z,y);printf(“%c-%cn“,x,z);move(n-1,y,x,z); ,a b c,. move(n,a,b,c);.,a-c,a-b,c-b,a-c,b-a,b-c,a-c,7.8 变量作用域 所谓变量的作用域, 是指该变量定义和使用的范围。变

30、量是对程序中数据的存储空间的抽象,编译或函数调用时为其分配内存单元,10,程序中使用变量名对内存操作,根据变量作用域不同, 变量分为局部变量和全局变量 7.8.1 局部变量 所谓局部变量,是指作用域在某程序块(函数)中的变量 1局部变量的定义位置及作用域 在函数体中的第一条可执行语句之前。 在复合语句中的第一条可执行语句之前 说明:局部变量的使用范围仅限于定义它的程序块不同函数中的变量可以同名,它们互不影响形式参数也属于局部变量main函数定义的变量也仅在main函数中有效,2局部变量的初始值与初始化所谓变量的初始化就是在定义变量的同时, 赋给该变量一个确定的初始值。 动态局部变量定义时如果没

31、有赋初始值,它的值是不确定的,所分配的存储单元中原来存放的值就是该变量初始值。一般情况下变量在必须先赋值,后引用;如果定义时没有赋初始值,应该在引用之前用语句给它赋值。 如:int i,s=0;for (i=1;i=10;i+) s=s+i;,int max(int a,int b); main() int x,y; /* 其作用域在main函数中*/if (xy) int z; /* 其作用域在复合语句中*/z=x*x-y*y;printf(“%dn”,z); int max(int a,int b),main() int x=10;int x=20;printf(“%d,”,x); pri

32、ntf(“%dn”,x); ,运行结果: 20,10,7.8.2 全局变量全局变量是指在任何函数之外定义的变量 有效范围是从定义开始,直至整个程序结束 定义一个全局变量的目的就是让多个函数可以共享 全局变量的定义在函数外定义,int a,b=3; main() int i,j;. char ch; float add(float x,float y) ,int fun( ); int n=5; main( ) int x;printf(“%dn”,n);x=fun( );printf(“%d,%dn”,x,n); int fun( ) int a=4;n=a;return n;,运行结果: 5

33、 4,4,#include int d=1; fun(int p) int d=5;d+=p+;printf(“%d,”d); main( ) int a=3;fun(a);d+=a+;printf(“%dn”,d); ,运行结果: 8,4,1全局变量的初始值 全局变量在编译阶段分配内存,在执行阶段不释放 全局变量只进行一次初始化,并且只能用常量 如果程序中没有给全局变量初始化,系统自动置02全局变量的作用 增加函数间数据的联系通道及数据共享;主要表现在: (1) 如果在一个程序的开始处定义了全局变量,则这个程序中的所有函数都能引用全局变量,在一个函数中改变了全局变量的值,其他函数中就可以访问

34、这个改变了的变量,相当于多了一个数据传递的通道。 (2) 由于函数的调用只能带回一个返回值,在需要带回两个以上的结果时,可以使用全局变量。,例5.8 利用函数完成交换两个变量的值。 int a,b; main() void swap();scanf(“%d,%d“, ,3全局变量的缺点可以看到, 当程序中的多个函数之间, 需要传递数据时, 全局变量也是可行的手段之一。但是, 必须避免全局变量的滥用。原因在于:(1)全局变量是静态的, 在程序的整个运行过程中都要占用内存单元, 可能造成内存资源的浪费。(2)使用全局变量使函数的通用性较差,如例5.8中的 swap 函数, 它只能完成变量a和b的交

35、换。(3)在编写大型程序时, 由于某全局变量值在别处意外的被修改而使程序出错。大量使用全局变量, 很容易产生这种副作用, 而且这种错误往往是防不胜防, 很难控制。根本的原因在于, 各模块之间除了用参数传递信息外, 还有许多意想不到的渠道, 降低了模块的独立性, 给程序设计、调试和维护工作造成困难。,变量在某一时刻存在-静态变量与动态变量 静态变量:从程序开始执行到程序结束 动态变量:从包含该变量定义的函数开始执行至函数执行结束,生存期,例 文件file1.c int a; main( ) .f2; .f1;. f1( ) int b;f2; f2( ) static int c; ,变量的存储

36、类别,存储类别: 是数据在内存中存储的方法.,分类: 自动的(auto),静态的(static),寄存器的(register),外部的(extern),自动的(auto):动态局部变量,默认类别,静态的(static),声明局部变量时:静态局部变量,声明全局变量时:该变量只被本文件使用,自动变量,自动变量是最常见的一类变量,将变量的存储属性定义为形式: auto 类型说明符 变量名; 一般地说,不加说明的变量都属于自动变量,因此: auto int a; 等价于 int a; auto float b; 等价于 float b; auto char str100 等价于 char str100

37、; 自动变量的说明必须在一个函数体的内部进行,函数的形参也是自动变量。自动变量的作用域是在所说明的函数中。 自动变量实质上是一个函数内部的局部变量。只有该函数被调用时它才存在,从函数中返回时即消失,它们的值也仅限于说明它的函数,其它函数不能存取。自动变量随函数的引用与否而存在和消失,在两次调用之间自动变量不会保持变量值,因此每次调用函数时都必须首先为自动变量赋值后才能使用(参加运算)。如果不置初值,则变量的值为随机的不定值。由于自动变量具有局部性,所以在两个函数中可以分别使用同名的变量而互不影响。,例:分析程序打印结果: main( ) int x=1; /* 函数main中的自动变量x */

38、 void f1( ), f2( ); f1( ); f2(x); /* 分别调用函数f1和f2 */ printf (“x=%dn”, x); void f1(void) int x=3; /* 函数f1中的自动变量x */ printf (“x=%dt”, x); void f2(x)/* 函数f2中的形参x也是自动变量,类型默认为int */ printf (“x=%dt“, +x); /* x加1 */ ,程序中有三个“x“分别在三个不同的函数中,这三个“x“都是自动变量,所以三个“x“分别局部于三不同的函数,在三个函数中对“x“的操作互不影响,故运行程序打印如下结果:x=3 x=2

39、x=1,外部变量,外部变量的定义形式是: extern 类型说明符 变量名; 所谓“外部”是相对于函数“内部”而言的,语言的外部变量就是定义在所有函数之外的全局变量。它可以被所有的函数访问,在所有函数体的内部都是有效的,所以函数之间可以通过外部变量直接传递数据 。,外部变量在编译的时侯由系统分配永久的存储空间。,#include int x; /* 说明外部变量x */ main( ) void addone( ), subone( ); x=1; /* 为外部变量x赋值 */ printf (“x begins is %dn“, x); addone ( ); subone ( ); sub

40、one ( ); addone ( ); addone ( ); printf (“x winds up as %dn“, x); ,分析程序运行结果。,void addone ( void ) /* 使用外部变量x */x+; printf (“add 1 to make %dn“, x); void subone(void) x-; /* 使用外部变量x */ printf (“substract 1 to make %dn“, x); ,在程序的最前面语句“int x;”说明了变量x;该说明语句的位置在所有函数之外,所以变量“x”为外部变量,对函数main、addone和subone来说

41、,变量x是全局变量,在这些函数的内部都是有效的。,如果外部变量的说明与使用在同一个文件中,则在该文件中的函数在使用外部变量时,不需要再进行其它的说明,可以直接使用。当外部变量的说明与使用在两个不同的文件,要使用其它文件中说明的外部变量,就必须在使用该外部变量之前,使用“extern”存储类型说明符进行变量“外部”说明。“extern”仅仅是说明变量是“外部的”,以及它的类型,并不真正分配存储空间。在将若干个文件连接生成一个完整的可运行程序时,系统会将不同文件中使用的同一外部变量连在一起,使用同一系统分配的存储单元。 语言中不仅有外部变量,而且有外部函数。由于语言不允许在函数内部再定义函数,所以

42、一个函数相对于另一函数本身就是外部的。当要调用的函数在另一个文件中时,在要调用的函数中,无论被调用的函数是什么类型,都必须用“extern“说明符说明被调用函数是“外部函数“。,/* file1.c */ /* 定义外部变量x和y */ int x = 10; int y = 10; void add ( void ) y=10+x; x*=2; main ( ) /* 在调用函数中说明函数sub是void型的外部函数 */extern void sub( ); x += 5;/* 分别调用函数 */ add( ); sub( ); printf (“x=%d; y=%dn“, x, y);

43、,/* file2.c */ /* 函数sub定义在另一个文件中 */ void sub (void) /* 说明定义在另一个文件中的外部变量x */ extern int x; x -= 5; ,程序编译后进行连接,文件一和文件二中的外部变量x会连接在一起,使用同一系统分配的存储单元。 运行程序,在main中执行语句“x+=5“,即x=10+5=15;然后调用add函数执行“y=10+x“,y=10+15=25,执行“x*=2“,x=15*2=30;返回main函数后再调用sub函数,执行“x-=5“,x=30-5=25。程序最终运行结果为:x=25; y=25,/* file1.c */

44、/* 定义外部变量x和y */ int x = 10; int y = 10; extern void sub( ); void add ( void ) int y=5; /* 说明自动变量y */ y=10+x; x *= 2; printf(“add:y=%d; “, y); main ( ) x += 5; add( ); sub( ); /* 分别调用函数 */ printf (“main:x=%d; main:y=%dn“, x, y); ,/* file2.c */ extern int x; /* 说明另一文件中的外部变量x */ void sub(void) int y=5;

45、 /* 说明自动变量y */ x -= y; printf(“sub:y=%d; “, y); ,本程序与上例比较,在add函数内部使用“int y=5”语句定义了变量y。add函数内部的变量“y“与外部变量“y“不是同一变量。外部变量“y“是全局变量,在所有函数内部有效,而函数add中定义的变量“y“是自动变量,它局部于函数add本身。两个变量根本不同。由于函数add内部已经重新说明了同名的自动变量“y“,所以外部变量“y“在函数add内部是不可见的,函数add不能再对外部变量y进行数据存取。所以在add内部“y=10+x“仅仅是修改了自动变量“y“的值,而对外部变量“y“的值无丝毫影响,同

46、样在函数sub内部也定义了一个自动变量y。调用sub函数,执行“y=5“,这时的“y“是sub内部定义的自动变量,它的值为5,与外部变量“y“没任何关系。在sub()执行语句中“x-=y“时的取值是自动变量y的值。所以程序运行结果为:add:y=25; sub:y=5; main:x=25; main:y=10,静态变量,静态变量是存放在内存中的静态存储区。编译系统为其分配固定的存储空间,重复使用时,变量的值保留。静态变量定义的形式是: static 类型标识符 变量名; 静态变量有两种:一种是内部静态变量,另一种是外部静态变量 注意:外部静态变量与外部变量有相似的地方,它是一种公用的全局变量

47、,但作用域仅仅在定义它的那个文件中,出了该文件不管是否用extern说明都是不可见的。简单地讲,外部静态变量仅仅作用于定义它的一个文件,而外部变量作用于整个程序。,内部静态变量,内部静态变量与自动变量有相似之处。内部静态变量也是局限于一个特定的函数,出了定义它的函数,即使对于同一文件中的其它函数也是不可见的。但它又不象自动变量那样,仅当定义自动变量的函数被调用时才存在,退出函数调用就消失。内部静态变量是始终存在的,当函数被调用退出后,内部静态变量会保存数值,再次调用该函数时,以前调用时的数值仍然保留着。编译系统为函数的内部静态变量分配专用的永久性的存储单元。,例: fun(int a,int b) static int m=0,i=2;i+=m+1;m+=i+a+b;return(m); main( ) int k=4,m=1,p;p=fun(k,m);printf(“%dn”,p);p=fun(k,m);printf(“%dn”,p); ,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 网络科技 > C/C++资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报