版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第六章 模块化程序设计与C语言函数模块化程序设计基础1函数的声明、定义和调用2程序设计实例4变量的存储属性310/2/2022第六章 模块化程序设计与C语言函数模块化程序设计基础1函数的6.1.1 模块化程序设计1. 模块化程序设计基本思想基本思想:将程序按功能分割成小模块。开发方法: FTTB,逐步分解,分而治之。特点和作用:模块独立,功能单一,结构清晰,接口简单。控制了程序设计的复杂性。提高模块元件的可靠性。缩短开发周期。避免程序开发的重复劳动。易于维护和功能扩充。 FBTT方法与FTTB方法6.1 模块化程序设计基础What to do ?How to do ?10/2/20226.1.
2、1 模块化程序设计6.1 模块化程序设计基础What模块化程序设计的方法基础。特点:把复杂问题的求解过程分步骤进行。面向目标。采取先全局、后局部的逐步分解思想。有利于将更多精力集中于较小模块的局部设计中。避免了盲目性。降低了系统设计与实现的整体工作量。FTTB(From Top To Bottom)10/2/2022模块化程序设计的方法基础。FTTB(From Top To 实践中:FBTT与FTTB结合来解决问题。在问题求解步骤和方法的确定上用FTTB方法,在将所有模块构成一个整体时用FBTT方法。FBTT(From Bottom To Top)例6-1 以FTTB、逐步求精的模块化分解思想
3、,分析1948年下半年解放战争战略决战问题。P125-12610/2/2022实践中:FBTT与FTTB结合来解决问题。在问题求解步骤和方例6-2 求1+2+100的和。分析:问题可分为三个部分,对应三个模块:1) 确定求值范围2) 计算过程3) 输出结果给定求和的上界计算i从1到给定上界的和输出所求的和值用选定方法求和10/2/2022例6-2 求1+2+100的和。给定求和的上界计算i从1 例6-3 分析九九乘法表输出功能。分析九九表的形状(例如第一种)。打印九行,每行分成两个部分:前导空格和九九表的口诀内容。右上角九九表输出九行输出某行i口诀构成:3*3 9 (即i*j=i*j)输出第i
4、行前导空格输出第i行口诀输出第i行的i-1个前导空格口诀输出第i行第k个前导空格口诀输出第i行9-i+1个口诀输出第i行第k个口诀空格口诀与口诀字符结构相同10/2/2022 例6-3 分析九九乘法表输出功能。右上角九九表输出九行输出2. 模块化程序的基本特征模块的IPO结构:要注意模块功能的独立性、完成功能所需的参数和提供给外界的输出信息。 模块的接口问题:唯一的通信渠道。应保证接口的单入口和单出口特征。模块的功能问题:大小要合适;具有较强的独立性和相对简单性;内部实现方法也应按照结构化程序设计思想进行组织和设计。10/2/20222. 模块化程序的基本特征9/24/20226.1.2 C语
5、言对模块化程序设计技术的支持1. 函数式程序语言结构函数带入函数参数带出计算结果图6-6 C语言函数的基本结构10/2/20226.1.2 C语言对模块化程序设计技术的支持1. 函数式程序float average(float fA,float fB,float fC) float fAve; fAve=(fA+fB+fC)/3; return fAve; /*End of average()*/外部向内部传递信息内部控制信息由内部向外传递信息1. 允许进行模块内部及外部的信息交换3. 具有编译预能力以方便模块化调试和移植10/2/2022float average(float fA,floa
6、t f6.2.1 C 语言程序的组织结构6.2 函数的声明、定义和调用结构源程序n函数1函数2函数m源程序i源程序1C程序声明区执行体10/2/20226.2.1 C 语言程序的组织结构6.2 函数的声明、定义和6.2.2 函数声明与定义从用户角度分为:标准函数(库函数):由系统提供。用户自定义函数:由程序员提供。从函数形式上分为:无参函数有参函数使用库函数应注意:1) 函数完成的功能 2) 参数数目和顺序及各参数意义和类型 3) 返回值的意义和类型4) 调用函数所需的包含文件(头文件)先声明、后定义、再引用10/2/20226.2.2 函数声明与定义使用库函数应注意:先声明、后定义、1. 函
7、数的声明(Function Declaration)声明的作用:告诉编译器函数类型、参数个数及类型,以便进行类型检验,保证调用的数据传递的正确性。对被调用函数的要求:函数已经被定义,即函数存在对库函数,知道库的头文件.h对自定义函数,有函数类型声明函数声明(函数原型声明)的一般形式: 函数类型 函数名(形参类型1 形参名1,形参类型n 形参名n) ; 或 函数类型 函数名() ;P129:函数的声明形参数据类型和顺序很重要必须要用分号结束10/2/20221. 函数的声明(Function Declaration)函数定义与函数声明不同函数声明的位置(P133)下列情况,可不作函数声明:对ch
8、ar或int型函数(隐含声明)函数的定义出现在主调函数之前有些系统要求函数声明指出函数返值和形参类型,即使对void和int型函数也要进行函数说明(如Borland C+)P130-13310/2/2022函数定义与函数声明不同P130-1339/24/2022一个完整形式的函数声明/*exam0604a.c:完整形式的函数声明*/#include int main(void)float fA=1,fB=2,fC=3;float sum(float fA,float fB,float fC); /*声明*/printf(sum=%fn,sum(fA,fB,fC); /*调用*/return 0
9、; /*End of main()*/float sum(float fA,float fB,float fC) /*定义*/return (fA+fB+fC); /*End of sum()*/例6-4 函数声明实例。声明了一个float型函数sum() sum函数的定义sum()函数有三个形式参数观察函数的声明和定义的区别10/2/2022一个完整形式的函数声明例6-4 函数声明实例。声明了一个fl允许声明与定义的参数名字不同#include /*exam0604b.c*/int main(void) float x=1,y=2,z=3;float sum(float x,float y,
10、float z);/*声明参数名*/printf(sum=%fn,sum(x+y,y,z);/*实参名*/return 0; /*End of main()*/float sum(float a,float b,float c)/*定义体参数名*/return (a+b+c); /*End of sum()*/10/2/2022允许声明与定义的参数名字不同9/24/2022声明时可不给参数名,但类型要一一对应#include /*exam0604c.c*/int main(void) float x=1,y=2,z=3;float sum(float,float,float ); /*声明*/
11、printf(sum=%fn,sum(x,y,z); /*实参*/return 0; /*End of main()*/float sum(float a,float b,float c) return (a+b+c); /*End of sum()*/10/2/2022声明时可不给参数名,但类型要一一对应9/24/2022/*exam0604d.c*/#include int main(void)float x=1,y=2,z=3;float sum(int a,float b,float c); /*声明*/printf(sum=%fn,sum(x,y,z); /*调用*/return 0
12、; /*End of main()*/float sum(float a, float b, float c) /*定义*/return (a+b+c); /*End of sum()*/类型不一致出错信息:Type mismatch in redeclaration of sum10/2/2022/*exam0604d.c*/类型不一致出错信息:9/24/*定义时参数名不能省略*/#include int main(void) float x=1,y=2,z=3;float sum(float a,float b,float c); /*声明*/printf(sum=%fn,sum(x,y,
13、z); /*调用*/return 0; /*End of main()*/float sum(float, float,float) /*定义*/return (a+b+c); /*End of sum()*/ 定义时省略了参数名出错信息:Argument missing name in function sumUndefined symbol a in function sumUndefined symbol b in function sum Undefined symbol c in function sum10/2/2022/*定义时参数名不能省略*/定义时省略了参数名出错信息:9/2
14、. 函数定义(Function Definition)是完成模块功能实现的主要工作。它对应一个分程序功能,也称为函数体。定义一般格式:合法标识符函数类型 函数名(类型1 形参1, ,类型n 形参n) 声明区域 /*变量或函数等的声明*/ 执行语句区域 /*可执行命令序列*/ 返回命令 /*retrun*/现代风格:函数体函数返回值类型。缺省时为int或void10/2/20222. 函数定义(Function Definition)合法例 有参函数(现代风格)int max(int nX,int nY) int nZ; nZ=nXnY?nX:nY; return(nZ); /*End of m
15、ax()*/例 有参函数(现代风格) int max(int nX, nY) int nZ; nZ=nXnY?nX:nY; return(nZ); /*End of max()*/例 空函数dummy() /*End of dummy()*/函数体为空例 无参函数printStar() printf(*n); /*End of printStar()*/或printStar(void ) printf(*n”); /*End of printStar()*/10/2/2022例 有参函数(现代风格)例 有参函数(现代风格)例 空函函数类型 函数名(形参名1,形参名n)数据类型1 形参名1;数据
16、类型n 形参名n; 语句组早期的函数定义经典方法double sum(n1,n2,d1,d2)double d1,d2;int n1,n2; return (n1+n2+d1+d2); /*End of sum()*/函数类型形参名列表声明次序和现代格式的区别参数类型10/2/2022函数类型 函数名(形参名1,形参名n)早期的函数定义经典#include float average(float val_1,float val_2,float val_3);int main(void) float x=1,y=2,z=3,q=4,t=5;float ave_1,ave_2; /*存放返回结果*
17、/ave_1=average(x,y,z); printf(ave_1=%fn,ave_1); ave_2=average(x,q,t); printf(ave_2=%fn,ave_2); return 0; /*End of main()*/float average(float val_1,float val_2,float val_3) float ave;ave=(val_1+val_2+val_3)/3.0;return ave; /*End of average()*/文件包含编译预处理命令函数声明函数调用函数调用函数定义10/2/2022#include 文件包含编译预处理命令函
18、3. 函数的返回值返回语句格式:return (表达式); 或 return 表达式; 或 return;功能:使控制从被调用函数返回到调用函数,同时把返值带给调用函数。说明:一个函数可有多个return语句。若无return语句,遇函数的时,自动返回调用函数。若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换函数调用转换。void型函数。例 无返回值函数。void swap(int x,int y) int temp; temp=x; x=y; y=temp; /*End of swap()*/10/2/20223. 函数的返回值例 无返回值函数。9/24/2022pr
19、intStar() printf(*); /*End of printStar*/int main(void) int nA; nA=printStar(); printf(%d,nA); /*End of main()*/例 函数带回不确定值。输出:*5void printStar() printf(*); /*End of printStar*/int main(void) int nA; nA=printStar(); printf(%d,nA); /*End of main()*/编译错误!Error: Not an allowed type in function main10/2/
20、2022printStar()例 函数带回不确定值。输出:*例 函数返回值类型转换#includeint max(float fA,float fB);int main(void) float fA,fB; int nC; scanf(%f,%f,&fA,&fB); nC=max(fA,fB); printf(Max is %dn,nC); /*End of main()*/int max(float fX, float fY) float fZ; fZ=fXfY?fX:fY; return(fZ); /*End of max()*/返回值要自动转换成整型!10/2/2022例 函数返回值类型
21、转换#include返回6.2.3 函数的调用 参数是函数调用时的信息交换载体,其传递是函数调用过程的重要环节。 C语言函数调用分为传值调用和传地址调用(第九章)两种。1. 函数的传值调用调用方法:函数名(实参表)说明:实参与形参个数相等,类型一致,按顺序一一对应10/2/20226.2.3 函数的调用 参数是函数调用时的信息float sum(float fA,float fB,float fC) return sum; /*End of sum()*/函数的IO信息路径10/2/2022float sum(float fA,float fB,fl注意函数参数求值顺序:自右向左。#inclu
22、deint f(int nA,int nB);int main(void) int i=2,nP; nP=f(i,+i); printf(%d,%d,nP,i); return 0; /*End of main()*/int f(int nA, int nB) int nC; if (nAnB) nC=1; else if (nA=nB) nC=0; else nC=-1; return(nC); /*End of f()*/运行结果:0,3#includeint f(int nA,int nB);int main(void) int i=2,nP; nP=f(i, i+); printf(%
23、d,nP); return 0; /*End of main()*/int f(int nA, int nB) int nC; if (nAnB) nC=1; else if (nA=nB) nC=0; else nC=-1; return(nC); /*End of f()*/运行结果:1,310/2/2022注意函数参数求值顺序:自右向左。#includey?x:y; return(z); /*End of max()*/例 比较两个数并输出大者。#includeint max(int x,int y);int main(void) int a,b,c; scanf(%d,%d,&a,&b
24、); c=max(a,b); printf(Max is %d,c); /*End of main()*/int max(int x, int y) int z; z=xy?x:y; return(z); /*End of max()*/形参实参10/2/2022形参与实参c=max(a,b);main()max()int说明:实参必须有确定的值形参必须指定类型形参与实参类型一致,个数相同若形参与实参类型不一致,自动按形参类型转换函数调用转换形参在调用前不占内存;调用执行时为形参分配内存;调用结束,释放空间。其存储空间是不固定的且值是不可继承的实参是特定存储空间中的值,在调用期间值不会发生变化
25、且存储空间相对固定10/2/2022说明:9/24/2022例6-7 形参和实参的虚实结合实例。#include float average(float val_1,float val_2,float val_3) float ave;ave=(val_1+val_2+val_3)/3.0;return ave; /*End of average()*/int main(void) float x=1,y=2,z=3,q=4,t=5; float ave_1,ave_2; ave_1=average(x,y,z); printf(ave_1=%fn,ave_1); ave_2=average(
26、x,q,t); printf(ave_2=%fn,ave_2); return 0; /*End of main()*/65470654746548665490654946547865482 1.000000 2.000000 3.0000004.0000005.000000*xytave_1ave_2zq*val_2val_1val_31.0000002.0000003.0000002.0000001.0000004.0000005.0000003.33333310/2/2022例6-7 形参和实参的虚实结合实例。654706547465参数传递方式值传递方式:函数调用时为形参分配单元,并将
27、实参值复制到形参中;调用结束时形参单元被释放,实参单元仍保留并维持原值值传递特点:形参与实参占用不同的内存单元。单向传递。10/2/2022参数传递方式9/24/20221020 x:y:调用前:调用后:1020 x:y:例6-8 交换两个数。#include void swap(int a,int b);int main(void) int x=10,y=20; printf(x=%d,y=%dn,x,y); printf(swapped:n); swap(x,y); printf(x=%d,y=%dn,x,y); /*End of main()*/void swap(int a,int b
28、) int temp; temp=a; a=b; b=temp; /*End of swap()*/调用:1020a:b:1020 x:y:swap():1020 x:y:2010a:b:temp这里可以看:到x,y的值并没有发生变化,想要交换主函数中的变量x和y的值,该如何处理呢?10/2/20221020 x:y:调用前:调用后:1020 x:y:例6-8 地址传递方式:函数调用时,将实参的存储地址作为参数值传递给形参的参数传递方式。实质上也是值传递,不过穿的是形参的地址值,而不是形参所在存储空间中的数据值。传地址值的特点:形参与实参占用(指向)同样的存储单元“双向”传递实参和形参必须是地
29、址10/2/2022地址传递方式:函数调用时,将实参的存储地址作为参数值传递给形例 交换两个数x59y调前:xp159y调swap:&x&yp2x95y交换:p1&x&yp2x95y返回:void swap(int *p1,int *p2) int p; p=*p1; *p1=*p2; *p2=p; /*End of swap()*/int main(void) int x,y; scanf(%d,%d,&x,&y); printf(x=%d,y=%dn,x,y); printf(swapped:n); swap(&x,&y); printf(x=%d,y=%dn,x,y); return 0
30、; /*End of main()*/10/2/2022例 交换两个数x59y调前:xp159y调swap:&x&2. 函数嵌套调用函数定义不可嵌套,但调用可以嵌套main()调用函数f1return 0;f1函数f2函数调用函数f210/2/20222. 函数嵌套调用main()调用函数f1return 0;例6-10 计算一个数的绝对值平方根。float absoluteValue(float x); float squareRoot(float x);float absoluteValue(float x) if (x=epsilon) guessValue=(x/guessValue+
31、guessValue)/2.0; return guessValue; /*End of square()*/int main(void) printf(SquareRoot(2.0)=%fn,squareRoot(2.0);return 0; /*End of main()*/main()squareRoot(2.0)return 0;squareRoot()absoluteValue()x=absoluteValue(x)guessValue=absoluteValue(x/guessValue+guessValue)/2.0)return guessValue;return x;retu
32、rn x;10/2/2022例6-10 计算一个数的绝对值平方根。main()squar3. 函数的递归调用*函数直接或间接调用自己的调用f()调f()调f2()调f1()f1()f2()int f(int nX) int nY,nZ; nZ=f(nY); . return(2*nZ);int f1(int nX) int nY,nZ; nZ=f2(nY); . return (2*nZ);int f2(int nT) int nA,nC; nC=f1(nA); . return (3+nC);说明C语言对递归函数的自调用次数没有限制每调用函数一次,系统将在内存堆栈区分配空间,用于存放函数变量
33、、返回值等信息。所以递归次数过多可能引起堆栈溢出10/2/20223. 函数的递归调用*f()调f()调f2()调f1()f1例6-11 直接递归求n的阶乘。int fact(int num) if (num0) /*n0时继续求n!*/ nTemp=fact(n); printf(The %d!=%dn,n,nTemp); else printf(n must be greater than zero!n); return 0; /*End of main()*/10/2/2022例6-11 直接递归求n的阶乘。int fact(int nint main(void) nTemp=fact(
34、4); /*main()*/int fact(4) if (num=1) return 1; else return 4*fact(3); /*fact()*/int fact(3) if (num=1) return 1; else return 3*fact(2); /*fact()*/int fact(1) if (num=1) return 1; else return 1*fact(0); /*fact()*/int fact(2) if (num=1) return 1; else return 2*fact(1); /*fact()*/2*1=23*2=64*6=24nTemp=
35、24n=4时fact()的执行过程:10/2/2022int main(void)int fact(4) int例6-12 间接递归求n的阶乘。例6-13 Hanoi塔问题。10/2/2022例6-12 间接递归求n的阶乘。例6-13 Hanoi塔问题6.3 变量的存储属性变量属性研究的内容:可操作属性(数据类型属性)存储属性(数据在存储空间的分配与有效性属性)可改变属性(值型变量还是指针型变量)访问属性(直接访问还是间接访问) 可操作属性在第二章作过详细讨论,访问属性及值的可改变属性将在第九章讨论。10/2/20226.3 变量的存储属性变量属性研究的内容:9/24/20226.3.1 变量
36、的存储属性和可操作属性 由第二章的变量讨论知道,变量是对存放数据的存储空间及其值的一种抽象。变量声明、定义和使用的注意事项: 变量的存储数据类型问题。不同数据类型的存放格式各不相同,有效取值范围及能够进行的操作也有区别,它们是变量的操作属性; 变量的有效作用范围、所用存储器类别、有效作用时间段(生成周期)和存储数据类别等构成了变量的存储属性内容。引入10/2/20226.3.1 变量的存储属性和可操作属性 由第二C语言系统的内存映像堆栈区域(Stack)堆区域(Heap)全局变量区域(Global)C程序代码(Code)变量的4种存储属性类型说明修饰符auto自动变量(动态变量)static静
37、态变量register寄存器变量(动态变量)extern外部变量10/2/2022C语言系统的内存映像堆栈区域(Stack)堆区域(Heap)int average(int n1,int n2,int n3) int nX,nY;int nX,nY;int nX,nY;int main(void) int nX,nY;6.3.2 变量在语言程序代码中的位置属性在函数内部出现在分程序中出现在函数体外部出现在main()函数中出现函数参数作为函数返回值总结:局部变量参数变量全局变量外部变量10/2/2022int average(int n1,int n2,int 6.3.3 变量的生成周期及有效
38、作用范围按生存周期临时变量全程变量局部的全局的局部的1. 临时存储变量及其有效作用范围临时变量在程序执行时进行空间分配且局部有效,也称动态变量。特点:在执行的某一时刻动态建立,在另外一个时刻被动态撤销或回收。从位置上看,除了在函数体外声明外,没有static或extern修饰的都是临时变量。例如:函数的形参变量、函数或分程序内部所声明的寄存器变量和自动变量都属于动态变量。10/2/20226.3.3 变量的生成周期及有效作用范围按生存周期临时变量动态变量分为:自动变量和寄存器变量自动变量声明格式如下:auto 数据类型 变量名=常量表达式,; auto修饰可有可无。 函数体内部声明的变量、函数
39、参数变量和其它分程序中声明的变量都属于自动变量。 自动变量在程序段执行时临时建立和分配存储空间,离开时自动撤销以便资源被其他它序段重用。自动变量在声明它的分程序中有效10/2/2022动态变量分为:自动变量和寄存器变量自动变量自动变量在声明它的void prt(int n1,int n2) int nX,nY; printf(prts source n1=%d n2=%dn,n1,n2); nX=n1+10,nY=n2+10; printf(prt()s nX=%d nY=%dn,nX,nY); n1+;n2+; printf(prt()s modified n1=%d n2=%dn,n1,n
40、2); return; /*End of prt()*/int main(void) int nX=10,nY=20; printf(Before call:nX=%d nY=%dn,nX,nY); prt(nX,nY); printf(After call:nX=%d nY=%dn,nX,nY); return 0; /*End of main()*/Before call:nX=10 nY=20prt()s source: n1=10 n2=20prt()s nX=20 nY=30prt()s modified n1=11 n2=21After call:nX=10 nY=20prt()内
41、的自动变量main()内的自动变量可见:main()中的nX,nY调用prt()前后的值未发生变化例6-14 自动变量的局部有效性。思考形参n1,n2和实参nX,nY值的变化情况,体会函数调用时值传递的特点10/2/2022void prt(int n1,int n2) Befor例如:例14中main()的nX,nY及prt()中的nX, nY的存储空间分布与同名屏蔽问题。FFD4FFD6FFC8FFCA1020nXnY2030nYnXmain()中的nX,nY变量的地址和值prt()中的nX,nY变量地址和值地址地址内、外层同名变量的自动屏蔽值值自动变量在赋初值之前的值不确定多次调用函数时
42、,自动变量值不保留10/2/2022例如:例14中main()的nX,nY及prt()中的nX,例6-15 自动变量赋值之前的不确定性。int main(void)int num1,num2,num3; /*声明但不初始化*/float value1,value2;char ch;double dValue;printf(num1=%d num2=%d um3=%dn,num1,num2,num3);printf(value1=%f value2=%fn,value1,value2);printf(dValue=%lfn,dValue);printf(ch=%cn,ch);return 0;
43、/*End of main()*/第三次运行结果:num1=-44 num2=27617 num3=-48value1=0.000000 value2=0.000000dValue=0.000000ch=第一次运行结果:num1=104 num2=27 num3=-48value1=0.000000 value2=0.000000dValue=0.000000ch=第二次运行结果:num1=774 num2=0 num3=-48value1=0.000000 value2=0.000000dValue=0.000000ch=可见:对整型自动变量在不给初始值时它是不确定的10/2/2022例6-
44、15 自动变量赋值之前的不确定性。第三次运行结果:第一例6-16 函数的多次调用之间自动变量没有继承性。#include /*自动变量继承性测试*/int inheritance_test(int num1, int num2)int nX,nY; /*nX,nY为观察对象*/printf(Before modified:nX=%d nY=%dn,nX,nY);nX=num1-num2;nY=num1+num2; /*修正nX,nY*/printf(After modified:nX=%d nY=%dn,nX,nY);return 0; /*inheritance_test()*/int ma
45、in(void)int i;for(i=1;i5;i+) inheritance_test(i*i, i+i); /*5次调用*/return 0; /*End of main()*/Before modified:nX=1 nY=2444After modified:nX=-1 nY=3Before modified:nX=2 nY=2444After modified:nX=0 nY=8Before modified:nX=3 nY=2444After modified:nX=3 nY=15Before modified:nX=4 nY=2444After modified:nX=8 nY
46、=24结果分析:第一次调用后:nX=-1,nY=3;第二次调用计算赋值前,nX=2,nY=2444。它们与上次调用时最后计算结果完全不同,表明上次计算结果没有被保留下来。后续调用与此相似。nX和nY的随机性与具体编译器及执行环境有关。10/2/2022例6-16 函数的多次调用之间自动变量没有继承性。Befor寄存器变量声明格式如下:register 数据类型 变量名=常量表达式,;以寄存器方式存放,而不是主存储器。主要的优势是快,但寄存器数量资源有限。Register只能修饰局部变量和函数形参变量。例6-16 寄存器变量实例。(P151)10/2/2022寄存器变量例6-16 寄存器变量实例
47、。(P151)9/24/2. 全程存储变量全程变量(Gloabal (life period)Variable):变量所占存储空间在整个程序执行期间都有效程变量分为:静态全程变量和外部全程变量全程性与全局性的区别:全程性指的是变量的生存周期性或时间属性;全局性和局部性指的是变量在代码段中的有效作用范围或空间属性。10/2/20222. 全程存储变量全程变量(Gloabal (life pe静态变量声明格式如下:static 数据类型 变量名=常量表达式,;在编译时分配空间,且在程序执行期间都不变。从执行开始直到整个程序结束。是函数或文件中的永久变量,分为静态局部变量和静态全局变量。声明在函数、
48、分程序或文件内部的静态变量在外部不可见。但多次调用时值可以继承,以实现局部变量的继承性。必须初始化且用常量表达式。不显式初始化时,编译时的自动初始化的规定是:整型数据初值为0,浮点型数据值为0.0,字符数据为空格 。10/2/2022静态变量9/24/2022例6-18 静态局部变量和自动变量的可继承性对比。#include int main(void) void increment(void); increment(); increment(); increment(); return 0; /*End of main()*/void increment(void) int n=0; /*a
49、uto*/ n+; printf(n=%dn,n); return; /*End of increment()*/#include int main(void) void increment(void); increment(); increment(); increment(); return 0; /*End of main()*/void increment(void) static int n=0; /*auto*/ n+; printf(n=%dn,n); return; /*End of increment()*/运行结果:n=1n=1n=1运行结果:n=1n=2n=3n无继承性n
50、有继承性10/2/2022例6-18 静态局部变量和自动变量的可继承性对比。#incl例6-19 静态局部变量的隐式初始化。#include void prt(void) /*输出静态局部变量的值*/static int num; /*声明局部静态变量但不作显式初始化*/static float val;static char ch;static long lNum;static double dVal;static long unsigned luNum;printf(num=%d, val=%f, ch=%c, ch=%dn,num,val,ch,ch);printf(lNum=%ld,
51、dVal=%lf, luNum=%lun,lNum,dVal,luNum);return; /*End of prt()*/int main(void)prt();return 0; /*End of main()*/运行测试结果:num=0, val=0.000000, ch= ,ch=0lNum=0, dVal=0.000000, luNum=0注意:1) 没有对静态局部变量显式初始化时,系统自行完成初始化。2) 在主函数中引用prt()的静态变量时,编译器将提示“Undefined symbol of num in function main”错误。它表明prt()中的静态局部变量在分程
52、序外部是不可见的,不能在外部进行引用。10/2/2022例6-19 静态局部变量的隐式初始化。运行测试结果:注意:1例6-20 静态局部变量的有效作用范围测试。#include void prt(void) static int nX=1; printf(In prt() before nX+=2:nX=%dn,nX); nX+=2; printf(In prt() after nX+=2:nX=%dn,nX); return; /*End of prt()*/int main(void) static int nX=10; printf(Before 1st prt() call:nX=%d
53、n,nX); prt();nX+; printf(After 1st prt() call:nX=%dn,nX); printf(Before 2nd prt() call:nX=%dn,nX); prt();nX+; printf(After 2nd prt() call:nX=%dn,nX); return 0; /*End of main()*/运行测试结果:Before 1st prt() call:nX=10In prt() before nX+=2:nX=1In prt() after nX+=2:nX=3After 1st prt() call:nX=11Before 2nd p
54、rt() call:nX=11In prt() before nX+=2:nX=3In prt() after nX+=2:nX=5After 2nd prt() call:nX=12注意: prt()内对nX的修改有继承性,但作用范围只能在prt()内,它影响不主函数中的nX。这正是模块化设计技术需要的特性。10/2/2022例6-20 静态局部变量的有效作用范围测试。运行测试结果:注全局变量(外部变量)声明:声明位置在函数体外部。整个程序可见,它可以被任何代码段引用。程序执行期间一直占用所分配存储空。必须进行声明初始化。否则,系统将自动初始化。初始化规定同静态变量。基本作用域从声明处直到所在文件末尾。所有外部变量不能重名,否则,编译器将报告错误信息“Redeclaration of 变量名”。但可以和函数体内的自动变量、参数变量以及其它类型的非外部变量重名。此时系统自动采用屏蔽技术进行重名处理。int nX,nY;int main(void)int nZ;float q;void f1()int nW;float f2()图6-2
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 背景图高级课程设计
- 物体旋转课程设计思路
- 体育行业市场拓展总结
- 应急科护士工作总结
- 电气技术实践课程设计
- 餐饮卫生的关键控制点
- 仪器仪表行业安全生产工作总结
- 肿瘤治疗护士工作总结
- 《病理学传染病》课件
- 2024年电能表修校工(中级工)职业鉴定考试题库(含答案)
- 国有企业考勤制度管理办法
- 人教版六年级上册道德与法治知识点
- 期货从业资格(期货基础知识)历年真题试卷汇编27
- 人工智能学习通超星期末考试答案章节答案2024年
- 北师大版(2019)必修第二册Unit 5 Humans and nature Lesson 3 Race to the pole教学设计
- 《毛概》23版学习通超星期末考试答案章节答案2024年
- 2024CSCO胰腺癌诊疗指南解读
- 窗帘采购投标方案(技术方案)
- 电力安全工作规程考试试题(答案)
- 2024-2030年串番茄行业市场发展分析及前景趋势与投资研究报告
- 城市燃气管网改造合同
评论
0/150
提交评论