模块化程序设计与语言函数_第1页
模块化程序设计与语言函数_第2页
模块化程序设计与语言函数_第3页
模块化程序设计与语言函数_第4页
模块化程序设计与语言函数_第5页
已阅读5页,还剩61页未读 继续免费阅读

下载本文档

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

文档简介

模块化程序设计与语言函数2023/6/1第一页,共六十六页,编辑于2023年,星期六6.1.1模块化程序设计1.模块化程序设计基本思想基本思想:将程序按功能分割成小模块。开发方法:

FTTB,逐步分解,分而治之。特点和作用:模块独立,功能单一,结构清晰,接口简单。控制了程序设计的复杂性。提高模块元件的可靠性。缩短开发周期。避免程序开发的重复劳动。易于维护和功能扩充。

FBTT方法与FTTB方法6.1模块化程序设计基础Whattodo?Howtodo?2023/6/1第二页,共六十六页,编辑于2023年,星期六模块化程序设计的方法基础。特点:把复杂问题的求解过程分步骤进行。面向目标。采取先全局、后局部的逐步分解思想。有利于将更多精力集中于较小模块的局部设计中。避免了盲目性。降低了系统设计与实现的整体工作量。FTTB(FromTopToBottom)2023/6/1第三页,共六十六页,编辑于2023年,星期六实践中:FBTT与FTTB结合来解决问题。在问题求解步骤和方法的确定上用FTTB方法,在将所有模块构成一个整体时用FBTT方法。FBTT(FromBottomToTop)例6-1

以FTTB、逐步求精的模块化分解思想,分析1948年下半年解放战争战略决战问题。P125-1262023/6/1第四页,共六十六页,编辑于2023年,星期六例6-2

求1+2+…+100的和。分析:问题可分为三个部分,对应三个模块:1)确定求值范围2)计算过程3)输出结果给定求和的上界计算i从1到给定上界的和输出所求的和值用选定方法求和2023/6/1第五页,共六十六页,编辑于2023年,星期六

例6-3

分析九九乘法表输出功能。分析九九表的形状(例如第一种)。打印九行,每行分成两个部分:前导空格和九九表的口诀内容。右上角九九表输出九行输出某行i口诀构成:"3*3=9"(即i*j=i*j)输出第i行前导空格输出第i行口诀输出第i行的i-1个前导空格口诀输出第i行第k个前导空格口诀输出第i行9-i+1个口诀输出第i行第k个口诀空格口诀与口诀字符结构相同2023/6/1第六页,共六十六页,编辑于2023年,星期六2.模块化程序的基本特征模块的IPO结构:要注意模块功能的独立性、完成功能所需的参数和提供给外界的输出信息。模块的接口问题:唯一的通信渠道。应保证接口的单入口和单出口特征。模块的功能问题:大小要合适;具有较强的独立性和相对简单性;内部实现方法也应按照结构化程序设计思想进行组织和设计。2023/6/1第七页,共六十六页,编辑于2023年,星期六6.1.2C语言对模块化程序设计技术的支持1.函数式程序语言结构函数带入函数参数带出计算结果图6-6C语言函数的基本结构2023/6/1第八页,共六十六页,编辑于2023年,星期六floataverage(floatfA,floatfB,floatfC){floatfAve;fAve=(fA+fB+fC)/3;returnfAve;}/*Endofaverage()*/外部向内部传递信息内部控制信息由内部向外传递信息1.允许进行模块内部及外部的信息交换3.具有编译预能力以方便模块化调试和移植2023/6/1第九页,共六十六页,编辑于2023年,星期六6.2.1C语言程序的组织结构6.2函数的声明、定义和调用结构源程序n函数1函数2函数m源程序i源程序1C程序……声明区执行体…2023/6/1第十页,共六十六页,编辑于2023年,星期六6.2.2函数声明与定义从用户角度分为:标准函数(库函数):由系统提供。用户自定义函数:由程序员提供。从函数形式上分为:无参函数有参函数使用库函数应注意:

1)函数完成的功能

2)参数数目和顺序及各参数意义和类型

3)返回值的意义和类型

4)调用函数所需的包含文件(头文件)先声明、后定义、再引用2023/6/1第十一页,共六十六页,编辑于2023年,星期六1.函数的声明(FunctionDeclaration)声明的作用:告诉编译器函数类型、参数个数及类型,以便进行类型检验,保证调用的数据传递的正确性。对被调用函数的要求:函数已经被定义,即函数存在对库函数,知道库的头文件.h对自定义函数,有函数类型声明函数声明(函数原型声明)的一般形式:

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

或函数类型函数名();P129:函数的声明形参数据类型和顺序很重要必须要用分号结束2023/6/1第十二页,共六十六页,编辑于2023年,星期六函数定义与函数声明不同函数声明的位置(P133)下列情况,可不作函数声明:对char或int型函数(隐含声明)函数的定义出现在主调函数之前有些系统要求函数声明指出函数返值和形参类型,即使对void和int型函数也要进行函数说明(如BorlandC++)P130-1332023/6/1第十三页,共六十六页,编辑于2023年,星期六一个完整形式的函数声明/*exam0604a.c::完整形式的函数声明*/#include<stdio.h>intmain(void){ floatfA=1,fB=2,fC=3;

floatsum(floatfA,floatfB,floatfC);

/*声明*/ printf("sum=%f\n",sum(fA,fB,fC));/*调用*/ return0;}

/*Endofmain()*/floatsum(floatfA,floatfB,floatfC)/*定义*/{ return(fA+fB+fC);}

/*Endofsum()*/例6-4

函数声明实例。声明了一个float型函数sum()sum函数的定义sum()函数有三个形式参数观察函数的声明和定义的区别2023/6/1第十四页,共六十六页,编辑于2023年,星期六允许声明与定义的参数名字不同#include<stdio.h>/*exam0604b.c*/intmain(void){ floatx=1,y=2,z=3; floatsum(floatx,floaty,floatz);/*声明参数名*/ printf("sum=%f\n",sum(x+y,y,z));/*实参名*/ return0;}/*Endofmain()*/floatsum(floata,floatb,floatc)/*定义体参数名*/{

return(a+b+c);}

/*Endofsum()*/2023/6/1第十五页,共六十六页,编辑于2023年,星期六声明时可不给参数名,但类型要一一对应#include<stdio.h>/*exam0604c.c*/intmain(void){ floatx=1,y=2,z=3; floatsum(float,float,float);

/*声明*/ printf("sum=%f\n",sum(x,y,z));/*实参*/ return0;}/*Endofmain()*/floatsum(floata,floatb,floatc){ return(a+b+c);}

/*Endofsum()*/2023/6/1第十六页,共六十六页,编辑于2023年,星期六/*exam0604d.c*/#include<stdio.h>intmain(void){ floatx=1,y=2,z=3; floatsum(inta,floatb,floatc);

/*声明*/ printf("sum=%f\n",sum(x,y,z));/*调用*/ return0;}/*Endofmain()*/floatsum(floata,floatb,floatc)/*定义*/{ return(a+b+c);}/*Endofsum()*/类型不一致出错信息:Typemismatchinredeclarationof'sum2023/6/1第十七页,共六十六页,编辑于2023年,星期六/*定义时参数名不能省略*/#include<stdio.h>intmain(void){ floatx=1,y=2,z=3; floatsum(floata,floatb,floatc);/*声明*/ printf("sum=%f\n",sum(x,y,z));/*调用*/ return0;}/*Endofmain()*/floatsum(float,float,float)/*定义*/{ return(a+b+c);}/*Endofsum()*/定义时省略了参数名出错信息:ArgumentmissingnameinfunctionsumUndefinedsymbol‘a’infunctionsumUndefinedsymbol‘b’infunctionsum

Undefinedsymbol'c'infunctionsum2023/6/1第十八页,共六十六页,编辑于2023年,星期六2.函数定义(FunctionDefinition)是完成模块功能实现的主要工作。它对应一个分程序功能,也称为函数体。定义一般格式:合法标识符函数类型函数名(类型1形参1,…,类型n形参n){

声明区域/*变量或函数等的声明*/

执行语句区域/*可执行命令序列*/

返回命令/*retrun*/}现代风格:函数体函数返回值类型。缺省时为int或void2023/6/1第十九页,共六十六页,编辑于2023年,星期六例有参函数(现代风格)intmax(intnX,intnY){intnZ;nZ=nX>nY?nX:nY;return(nZ);}/*Endofmax()*/例有参函数(现代风格)intmax(intnX,nY){intnZ;nZ=nX>nY?nX:nY;return(nZ);}/*Endofmax()*/例空函数dummy(){}/*Endofdummy()*/函数体为空例无参函数printStar(){printf("********\n");}/*EndofprintStar()*/或printStar(void){printf("********\n"”);}/*EndofprintStar()*/2023/6/1第二十页,共六十六页,编辑于2023年,星期六函数类型函数名(形参名1,…,形参名n)数据类型1形参名1;…数据类型n形参名n;{

语句组}早期的函数定义经典方法doublesum(n1,n2,d1,d2)doubled1,d2;intn1,n2;{return(n1+n2+d1+d2);}/*Endofsum()*/函数类型形参名列表声明次序和现代格式的区别参数类型2023/6/1第二十一页,共六十六页,编辑于2023年,星期六#include<stdio.h>floataverage(floatval_1,floatval_2,floatval_3);intmain(void){ floatx=1,y=2,z=3,q=4,t=5; floatave_1,ave_2;/*存放返回结果*/ ave_1=average(x,y,z); printf("ave_1=%f\n",ave_1); ave_2=average(x,q,t); printf("ave_2=%f\n",ave_2); return0;}/*Endofmain()*/floataverage(floatval_1,floatval_2,floatval_3){ floatave; ave=(val_1+val_2+val_3)/3.0; returnave;}/*Endofaverage()*/文件包含编译预处理命令函数声明函数调用函数调用函数定义2023/6/1第二十二页,共六十六页,编辑于2023年,星期六3.函数的返回值返回语句格式:return(表达式);

或return表达式;

或return;功能:使控制从被调用函数返回到调用函数,同时把返值带给调用函数。说明:一个函数可有多个return语句。若无return语句,遇函数的}时,自动返回调用函数。若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换——函数调用转换。void型函数。例无返回值函数。voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}/*Endofswap()*/2023/6/1第二十三页,共六十六页,编辑于2023年,星期六printStar(){printf("*****");}/*EndofprintStar*/intmain(void){intnA;nA=printStar();printf("%d",nA);}/*Endofmain()*/例函数带回不确定值。输出:*****5voidprintStar(){printf("*****");}/*EndofprintStar*/intmain(void){intnA;nA=printStar();printf("%d",nA);}/*Endofmain()*/编译错误!Error:Notanallowedtypeinfunctionmain2023/6/1第二十四页,共六十六页,编辑于2023年,星期六例函数返回值类型转换#include<stdio.h>intmax(floatfA,floatfB);intmain(void){floatfA,fB;

intnC;scanf("%f,%f",&fA,&fB);nC=max(fA,fB);printf("Maxis%d\n",nC);}/*Endofmain()*/intmax(floatfX,floatfY){

floatfZ;fZ=fX>fY?fX:fY;

return(fZ);}/*Endofmax()*/返回值要自动转换成整型!2023/6/1第二十五页,共六十六页,编辑于2023年,星期六6.2.3函数的调用参数是函数调用时的信息交换载体,其传递是函数调用过程的重要环节。

C语言函数调用分为传值调用和传地址调用(第九章)两种。1.函数的传值调用调用方法:函数名(实参表)说明:实参与形参个数相等,类型一致,按顺序一一对应2023/6/1第二十六页,共六十六页,编辑于2023年,星期六floatsum(floatfA,floatfB,floatfC){…returnsum;}/*Endofsum()*/

函数的IO信息路径2023/6/1第二十七页,共六十六页,编辑于2023年,星期六注意函数参数求值顺序:自右向左。#include<stdio.h>intf(intnA,intnB);intmain(void){inti=2,nP;nP=f(i,++i);printf("%d,%d",nP,i);return0;}/*Endofmain()*/intf(intnA,intnB){intnC;if(nA>nB)nC=1;elseif(nA==nB)nC=0;elsenC=-1;return(nC);}/*Endoff()*/运行结果:0,3#include<stdio.h>intf(intnA,intnB);intmain(void){inti=2,nP;nP=f(i,

i++);printf("%d",nP);return0;}/*Endofmain()*/intf(intnA,intnB){intnC;if(nA>nB)nC=1;elseif(nA==nB)nC=0;elsenC=-1;return(nC);}/*Endoff()*/运行结果:1,32023/6/1第二十八页,共六十六页,编辑于2023年,星期六函数调用可以用于表达式,可以单独成为一个语句,也可以是其它函数的参数。因此,其调用形式有:函数调用作为单独的语句例

printStar();printf("Hello,World!\n");函数调用用作表达式的运算成分例m=max(nA,nB)*2;函数调用作为其它函数的实参:例

printf("%d",max(nA,nB));m=max(nA,max(nB,nC));2023/6/1第二十九页,共六十六页,编辑于2023年,星期六形参与实参形参:定义函数时函数名后面括号中的变量名实参:调用函数时函数名后面括号中的表达式c=max(a,b);main()max()intmax(intx,inty){intz;z=x>y?x:y;return(z);}/*Endofmax()*/例比较两个数并输出大者。#include<stdio.h>intmax(intx,inty);intmain(void){inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis%d",c);}/*Endofmain()*/intmax(intx,inty){intz;z=x>y?x:y;return(z);}/*Endofmax()*/形参实参2023/6/1第三十页,共六十六页,编辑于2023年,星期六说明:实参必须有确定的值形参必须指定类型形参与实参类型一致,个数相同若形参与实参类型不一致,自动按形参类型转换——函数调用转换形参在调用前不占内存;调用执行时为形参分配内存;调用结束,释放空间。其存储空间是不固定的且值是不可继承的实参是特定存储空间中的值,在调用期间值不会发生变化且存储空间相对固定2023/6/1第三十一页,共六十六页,编辑于2023年,星期六例6-7

形参和实参的虚实结合实例。#include<stdio.h>floataverage(floatval_1,floatval_2,floatval_3){ floatave; ave=(val_1+val_2+val_3)/3.0; returnave;}/*Endofaverage()*/intmain(void){ floatx=1,y=2,z=3,q=4,t=5; floatave_1,ave_2; ave_1=average(x,y,z); printf("ave_1=%f\n",ave_1); ave_2=average(x,q,t); printf("ave_2=%f\n",ave_2); return0;}/*Endofmain()*/65470654746548665490654946547865482

1.000000

2.000000

3.0000004.0000005.000000********xytave_1ave_2zq******val_2val_1val_31.0000002.0000003.0000002.0000001.0000004.0000005.0000003.3333332023/6/1第三十二页,共六十六页,编辑于2023年,星期六参数传递方式值传递方式:函数调用时为形参分配单元,并将实参值复制到形参中;调用结束时形参单元被释放,实参单元仍保留并维持原值值传递特点:形参与实参占用不同的内存单元。单向传递。2023/6/1第三十三页,共六十六页,编辑于2023年,星期六1020x:y:调用前:调用后:1020x:y:例6-8

交换两个数。#include<stdio.h>voidswap(inta,intb);intmain(void){intx=10,y=20;printf("x=%d,y=%d\n",x,y);printf("swapped:\n");

swap(x,y);printf("x=%d,y=%d\n",x,y);}/*Endofmain()*/voidswap(inta,intb){inttemp;temp=a;a=b;b=temp;}/*Endofswap()*/调用:1020a:b:1020x:y:swap():1020x:y:2010a:b:temp这里可以看:到x,y的值并没有发生变化,想要交换主函数中的变量x和y的值,该如何处理呢?2023/6/1第三十四页,共六十六页,编辑于2023年,星期六地址传递方式:函数调用时,将实参的存储地址作为参数值传递给形参的参数传递方式。实质上也是值传递,不过穿的是形参的地址值,而不是形参所在存储空间中的数据值。传地址值的特点:形参与实参占用(指向)同样的存储单元“双向”传递实参和形参必须是地址2023/6/1第三十五页,共六十六页,编辑于2023年,星期六例交换两个数x59y调前:xp159y调swap:&x&yp2x95y交换:p1&x&yp2x95y返回:voidswap(int*p1,int*p2){intp;p=*p1;*p1=*p2;*p2=p;}/*Endofswap()*/intmain(void){intx,y;scanf("%d,%d",&x,&y);printf("x=%d,y=%d\n",x,y);printf("swapped:\n");swap(&x,&y);printf("x=%d,y=%d\n",x,y);return0;}/*Endofmain()*/2023/6/1第三十六页,共六十六页,编辑于2023年,星期六2.函数嵌套调用函数定义不可嵌套,但调用可以嵌套main()调用函数f1return0;f1函数f2函数调用函数f22023/6/1第三十七页,共六十六页,编辑于2023年,星期六例6-10

计算一个数的绝对值平方根。floatabsoluteValue(floatx);floatsquareRoot(floatx);floatabsoluteValue(floatx){ if(x<0)x=-x; returnx;}/*Endofabsolute()*/floatsquareRoot(floatx)

{ constfloatepsilon=0.00001,guessValue=1.0; x=absoluteValue(x);/*调用absoluteValue函数*/ while(absoluteValue(guessValue*guessValue-x)>=epsilon) guessValue=(x/guessValue+guessValue)/2.0; returnguessValue;}/*Endofsquare()*/intmain(void){ printf("SquareRoot(2.0)=%f\n",squareRoot(2.0)); return0;}/*Endofmain()*/main()squareRoot(2.0)return0;squareRoot()absoluteValue()x=absoluteValue(x)guessValue=absoluteValue(x/guessValue+guessValue)/2.0)returnguessValue;⑪⑩⑫⑬returnx;returnx;2023/6/1第三十八页,共六十六页,编辑于2023年,星期六3.函数的递归调用*函数直接或间接调用自己的调用f()调f()调f2()调f1()f1()f2()intf(intnX){intnY,nZ;……

nZ=f(nY);…….return(2*nZ);}intf1(intnX){intnY,nZ;……

nZ=f2(nY);…….return(2*nZ);}intf2(intnT){intnA,nC;……

nC=f1(nA);…….return(3+nC);}说明C语言对递归函数的自调用次数没有限制每调用函数一次,系统将在内存堆栈区分配空间,用于存放函数变量、返回值等信息。所以递归次数过多可能引起堆栈溢出2023/6/1第三十九页,共六十六页,编辑于2023年,星期六例6-11直接递归求n的阶乘。intfact(intnum){if(num<=1)return1;elsereturnnum*fact(num-1);

}/*Endoffact()*/intmain(void){intn,nTemp;/*nTemp=n!*/printf("Pleaseinputanumber:");scanf("%d",&n);if(n>0){/*n>0时继续求n!*/nTemp=fact(n);printf("The%d!=%d\n",n,nTemp);}elseprintf("nmustbegreaterthanzero!\n");return0;}/*Endofmain()*/2023/6/1第四十页,共六十六页,编辑于2023年,星期六intmain(void){……nTemp=fact(4);……}/*main()*/intfact(4){if(num<=1)return1;elsereturn4*fact(3);

}/*fact()*/intfact(3){if(num<=1)return1;elsereturn3*fact(2);

}/*fact()*/intfact(1){if(num<=1)

return1;

elsereturn1*fact(0);}/*fact()*/intfact(2){if(num<=1)return1;elsereturn2*fact(1);

}/*fact()*/2*1=23*2=64*6=24nTemp=24n=4时fact()的执行过程:2023/6/1第四十一页,共六十六页,编辑于2023年,星期六例6-12间接递归求n的阶乘。例6-13Hanoi塔问题。2023/6/1第四十二页,共六十六页,编辑于2023年,星期六6.3变量的存储属性变量属性研究的内容:可操作属性(数据类型属性)存储属性(数据在存储空间的分配与有效性属性)可改变属性(值型变量还是指针型变量)访问属性(直接访问还是间接访问)

可操作属性在第二章作过详细讨论,访问属性及值的可改变属性将在第九章讨论。2023/6/1第四十三页,共六十六页,编辑于2023年,星期六6.3.1变量的存储属性和可操作属性由第二章的变量讨论知道,变量是对存放数据的存储空间及其值的一种抽象。变量声明、定义和使用的注意事项:变量的存储数据类型问题。不同数据类型的存放格式各不相同,有效取值范围及能够进行的操作也有区别,它们是变量的操作属性;变量的有效作用范围、所用存储器类别、有效作用时间段(生成周期)和存储数据类别等构成了变量的存储属性内容。引入2023/6/1第四十四页,共六十六页,编辑于2023年,星期六C语言系统的内存映像堆栈区域(Stack)堆区域(Heap)全局变量区域(Global)C程序代码(Code)变量的4种存储属性类型说明修饰符auto—自动变量(动态变量)static—静态变量register—寄存器变量(动态变量)extern—外部变量2023/6/1第四十五页,共六十六页,编辑于2023年,星期六intaverage(intn1,intn2,intn3){intnX,nY;……{intnX,nY;……}}intnX,nY;intmain(void){intnX,nY;……}6.3.2变量在C语言程序代码中的位置属性③在函数内部出现④在分程序中出现⑤在函数体外部出现⑥在main()函数中出现①函数参数②作为函数返回值总结:局部变量参数变量全局变量外部变量2023/6/1第四十六页,共六十六页,编辑于2023年,星期六6.3.3变量的生成周期及有效作用范围按生存周期临时变量全程变量局部的全局的局部的1.临时存储变量及其有效作用范围临时变量在程序执行时进行空间分配且局部有效,也称动态变量。特点:在执行的某一时刻动态建立,在另外一个时刻被动态撤销或回收。从位置上看,除了在函数体外声明外,没有static或extern修饰的都是临时变量。例如:函数的形参变量、函数或分程序内部所声明的寄存器变量和自动变量都属于动态变量。2023/6/1第四十七页,共六十六页,编辑于2023年,星期六动态变量分为:自动变量和寄存器变量自动变量声明格式如下:

[auto]数据类型变量名[=常量表达式],…;

auto修饰可有可无。函数体内部声明的变量、函数参数变量和其它分程序中声明的变量都属于自动变量。自动变量在程序段执行时临时建立和分配存储空间,离开时自动撤销以便资源被其他它序段重用。自动变量在声明它的分程序中有效2023/6/1第四十八页,共六十六页,编辑于2023年,星期六voidprt(intn1,intn2){intnX,nY;printf("prt'ssourcen1=%dn2=%d\n",n1,n2);nX=n1+10,nY=n2+10;printf("prt()'snX=%dnY=%d\n",nX,nY);

n1++;n2++;printf("prt()'smodifiedn1=%dn2=%d\n",n1,n2);return;}/*Endofprt()*/intmain(void){intnX=10,nY=20;printf("Beforecall:nX=%dnY=%d\n",nX,nY);prt(nX,nY);printf("Aftercall:nX=%dnY=%d\n",nX,nY);return0;}/*Endofmain()*/Beforecall:nX=10nY=20prt()'ssource:n1=10n2=20prt()'snX=20nY=30prt()'smodifiedn1=11n2=21Aftercall:nX=10nY=20prt()内的自动变量main()内的自动变量可见:main()中的nX,nY调用prt()前后的值未发生变化例6-14

自动变量的局部有效性。思考形参n1,n2和实参nX,nY值的变化情况,体会函数调用时值传递的特点2023/6/1第四十九页,共六十六页,编辑于2023年,星期六例如:例14中main()的nX,nY及prt()中的nX,nY的存储空间分布与同名屏蔽问题。FFD4FFD6FFC8FFCA1020nXnY2030nYnXmain()中的nX,nY变量的地址和值prt()中的nX,nY变量地址和值地址地址内、外层同名变量的自动屏蔽值值自动变量在赋初值之前的值不确定多次调用函数时,自动变量值不保留2023/6/1第五十页,共六十六页,编辑于2023年,星期六例6-15

自动变量赋值之前的不确定性。intmain(void){ intnum1,num2,num3;/*声明但不初始化*/ floatvalue1,value2; charch; doubledValue; printf("num1=%dnum2=%dum3=%d\n",num1,num2,num3); printf("value1=%fvalue2=%f\n",value1,value2); printf("dValue=%lf\n",dValue); printf("ch=%c\n",ch); return0;}/*Endofmain()*/第三次运行结果:num1=-44num2=27617num3=-48value1=0.000000value2=0.000000dValue=0.000000ch=♀第一次运行结果:num1=104num2=27num3=-48value1=0.000000value2=0.000000dValue=0.000000ch=ÿ第二次运行结果:num1=774num2=0num3=-48value1=0.000000value2=0.000000dValue=0.000000ch=ÿ可见:对整型自动变量在不给初始值时它是不确定的2023/6/1第五十一页,共六十六页,编辑于2023年,星期六例6-16

函数的多次调用之间自动变量没有继承性。#include<stdio.h>/*自动变量继承性测试*/intinheritance_test(intnum1,intnum2){ intnX,nY;/*nX,nY为观察对象*/ printf("Beforemodified:nX=%dnY=%d\n",nX,nY);

nX=num1-num2;nY=num1+num2;/*修正nX,nY*/ printf("Aftermodified:nX=%dnY=%d\n",nX,nY); return0;}/*inheritance_test()*/intmain(void){ inti; for(i=1;i<5;i++)inheritance_test(i*i,i+i);/*5次调用*/ return0;}/*Endofmain()*/Beforemodified:nX=1nY=2444Aftermodified:nX=-1nY=3Beforemodified:nX=2nY=2444Aftermodified:nX=0

nY=8Beforemodified:nX=3nY=2444Aftermodified:nX=3

nY=15Beforemodified:nX=4nY=2444Aftermodified:nX=8

nY=24结果分析:第一次调用后:nX=-1,nY=3;第二次调用计算赋值前,nX=2,nY=2444。它们与上次调用时最后计算结果完全不同,表明上次计算结果没有被保留下来。后续调用与此相似。nX和nY的随机性与具体编译器及执行环境有关。2023/6/1第五十二页,共六十六页,编辑于2023年,星期六寄存器变量声明格式如下:

[register]数据类型变量名[=常量表达式],…;以寄存器方式存放,而不是主存储器。主要的优势是快,但寄存器数量资源有限。Register只能修饰局部变量和函数形参变量。例6-16

寄存器变量实例。(P151)2023/6/1第五十三页,共六十六页,编辑于2023年,星期六2.全程存储变量全程变量(Gloabal(lifeperiod)Variable):变量所占存储空间在整个程序执行期间都有效程变量分为:静态全程变量和外部全程变量全程性与全局性的区别:全程性指的是变量的生存周期性或时间属性;全局性和局部性指的是变量在代码段中的有效作用范围或空间属性。2023/6/1第五十四页,共六十六页,编辑于2023年,星期六静态变量声明格式如下:static数据类型变量名[=常量表达式],…;在编译时分配空间,且在程序执行期间都不变。从执行开始直到整个程序结束。是函数或文件中的永久变量,分为静态局部变量和静态全局变量。声明在函数、分程序或文件内部的静态变量在外部不可见。但多次调用时值可以继承,以实现局部变量的继承性。必须初始化且用常量表达式。不显式初始化时,编译时的自动初始化的规定是:整型数据初值为0,浮点型数据值为0.0,字符数据为空格''。2023/6/1第五十五页,共六十六页,编辑于2023年,星期六例6-18

静态局部变量和自动变量的可继承性对比。#include<stdio.h>intmain(void){voidincrement(void);increment();increment();increment();return0;}/*Endofmain()*/voidincrement(void){intn=0;/*auto*/n++;printf("n=%d\n",n);

return;}/*Endofincrement()*/#include<stdio.h>intmain(void){voidincrement(void);increment();increment();increment();return0;}/*Endofmain()*/voidincrement(void){

staticintn=0;/*auto*/n++;printf("n=%d\n",n);

return;}/*Endofincrement()*/运行结果:n=1n=1n=1运行结果:n=1n=2n=3n无继承性n有继承性2023/6/1第五十六页,共六十六页,编辑于2023年,星期六例6-19

静态局部变量的隐式初始化。#include<stdio.h>voidprt(void){/*输出静态局部变量的值*/

staticintnum;/*声明局部静态变量但不作显式初始化*/

staticfloatval;

staticcharch;

staticlonglNum;

staticdoubledVal;

staticlongunsignedluNum; printf("num=%d,val=%f,ch=%c,ch=%d\n",num,val,ch,ch); printf("lNum=%ld,dVal=%lf,luNum=%lu\n",lNum,dVal,luNum); return;}/*Endofprt()*/intmain(void){ prt(); return0;}/*Endofmain()*/运行测试结果:num=0,val=0.000000,ch=,ch=0lNum=0,dVal=0.000000,luNum=0注意:1)没有对静态局部变量显式初始化时,系统自行完成初始化。2)在主函数中引用prt()的静态变量时,编译器将提示“Undefinedsymbolof‘num’infunctionmain”错误。它表明prt()中的静态局部变量在分程序外部是不可见的,不能在外部进行引用。2023/6/1第五十七页,共六十六页,编辑于2023年,星期六例6-20静态局部变量的有效作用范围测试。#include<stdio.h>voidprt(void){staticintnX=1;printf("Inprt()beforenX+=2:nX=%d\n",nX);nX+=2;printf("Inprt()afternX+=2:nX=%d\n",nX);return;}/*Endofprt()*/intmain(void){staticintnX=10;printf("Before1stprt()call:nX=%d\n",nX);prt();nX++;printf("After1stprt()call:nX=%d\n",nX);printf("Before2ndprt()call:nX=%d\n",nX);prt();nX++;printf("After2ndprt()call:nX=%d\n",nX);return0;}/*Endofmain()*/运行测试结果:Before1stprt()call:nX=10Inprt()beforenX+=2:nX=1Inprt()afternX+=2:nX=3After1stprt()call:nX=11Before2ndprt()call:nX=11Inprt()beforenX+=2:nX=3Inprt()afternX+=2:nX=5After2ndprt()call:nX=12注意:

prt()内对nX的修改有继承性,但作用范围只能在prt()内,它影响不主函数中的nX。这正是模块化设计技术需要的特性。2023/6/1第五十八页,共六十六页,编辑于2023年,星期六全局变量(外部变量)声明:声明位置在函数体外部。整个程序可见,它可以被任何代码段引用。程序执行期间一直占用所分配存储空。必须进行声明初始化。否则,系统将自动初始化。初始化规定同静态变量。基本作用域从声明处直到所在文件末尾。所有外部变量不能重名,否则,编译器将报告错误信息“Redeclarationof变量名”。但可以和函数体内的自动变量、参数变量以及其它类型的非外部变量重名。此时系统自动采用屏蔽技术进行重名处理。intnX,nY;intmain(void){…}intnZ;floatq;

温馨提示

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

评论

0/150

提交评论