《(C++课件)4章 变量作用域第(函数2)(精品).ppt》由会员分享,可在线阅读,更多相关《(C++课件)4章 变量作用域第(函数2)(精品).ppt(25页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、4.3 全局变量和局部变量全局变量和局部变量4.3.1 4.3.1 变量的存储机制与变量的存储机制与变量的存储机制与变量的存储机制与C+C+的内存布局的内存布局的内存布局的内存布局 4.4.3.2 3.2 全局变量全局变量全局变量全局变量 4.4.3.3 3.3 局部变量局部变量局部变量局部变量 4.3.1 变量的存储机制与变量的存储机制与C+的内存布局的内存布局自由存储区自由存储区 (动态数据动态数据)操操作作系系统统为为一一个个C+C+程程序序的的运运行行所所分分配配的的内内存分为四个区域,如图存分为四个区域,如图4.34.3 所示:所示:栈区(函数局部数据)栈区(函数局部数据)全局数据区
2、全局数据区(全局、静态全局、静态)代码区(程序代码)代码区(程序代码)(main()函数局部数据)函数局部数据)自由存储区自由存储区 (动态数据动态数据)存储区域说明:存储区域说明:(1)代码区()代码区(Code area):存放程序代码,即程序):存放程序代码,即程序中各个函数的代码块;中各个函数的代码块;(2)全局数据区()全局数据区(Data area):存放全局数据和静态):存放全局数据和静态数据;数据;分配该区时内存全部清零分配该区时内存全部清零,结果变量的所有字节,结果变量的所有字节等效初始化为全等效初始化为全。(3)栈区()栈区(Stack area):存放局部变量,如函数中)
3、:存放局部变量,如函数中的变量等;的变量等;分配栈区时不处理内存分配栈区时不处理内存,即变量取随机值。,即变量取随机值。(4)自由存储区(自由存储区(Free store area):):存放与指针相存放与指针相关的动态数据。关的动态数据。分配分配自由存储自由存储区时不处理内存区时不处理内存。4.3.1 变量的存储机制与变量的存储机制与C+的内存布局的内存布局 4.3.2 全局变量全局变量 在在所有函数之外定义的变量称为所有函数之外定义的变量称为全局变量全局变量。全全局局变变量量存存放放在在全全局局数数据据区区,因因编编译译器器自自动动将将该该区区清清为为全全0,如如果果用用户户在在定定义义时
4、时不不显显式式给给出出初初始始化值,则化值,则等效初始化为全等效初始化为全0。全全局局变变量量可可定定义义在在程程序序开开头头,也也可可定定义义在在中中间间位位置置,该该全全局局变变量量在在定定义义处处之之后后的的任任何何位位置置都都是是可可以访问的,称为以访问的,称为可见的可见的。【例例4.5】多个函数使用全局变量的例子。多个函数使用全局变量的例子。全局变量引入:全局变量引入:4.3.2 全局变量全局变量【例例4.5】打印打印200调用调用func()函数函数func()200*2=400打印打印400n=100n=100*2=200【例例4.54.5】多个函数使用全局变量的例子。多个函数使
5、用全局变量的例子。int n=100;void func()n*=2;int main()n*=2;coutnendl;func();coutnendl;return 0;4.3.3 局部变量局部变量 定义在函数内或块内的变量称为定义在函数内或块内的变量称为局部变量局部变量。程序中使用的绝大多数变量都是局部变量。程序中使用的绝大多数变量都是局部变量。局局部部变变量量在在程程序序运运行行到到它它所所在在的的块块时时建建立立在在栈栈中中,该该块块执执行行完完毕毕局局部部变变量量占占有有的的空空间间即即被被释释放放。故故亦亦称称为为自动变量自动变量。局局部部变变量量在在定定义义时时可可加加修修饰饰词
6、词auto,但但通通常常省省略略。局部变量在定义时若未初始化,其值为局部变量在定义时若未初始化,其值为随机数随机数。局部变量引入:局部变量引入:【例例4.6】使用局部变量的例子。使用局部变量的例子。4.3.3 局部变量局部变量 打印打印main()中的中的t=4.5调用调用fun()函数函数fun()打印打印fun()中的中的t=5 打印打印main()中的中的t=4.5t=4.5t=5【例例4.6】使用局部变量的例子。使用局部变量的例子。void fun()auto int t=5;/fun()中的局部变量,中的局部变量,auto可省略可省略coutfun()中的中的t=tendl;int
7、main()float t=4.5;/main()函数中的局部变量函数中的局部变量coutmain()中中的的t=tendl;fun();coutmain()中中的的t=tendl;return 0;4.4 函数调用机制函数调用机制 局局部部变变量量占占用用的的内内存存是是在在程程序序执执行行过过程程中中“动动态态”地地建建立立和释放的。这种和释放的。这种“动态动态”是通过栈由系统是通过栈由系统自动自动管理进行的。管理进行的。(1)建立栈空间;)建立栈空间;(6)恢复现场:取主调函数运行状态及返回地址,释放栈空间;)恢复现场:取主调函数运行状态及返回地址,释放栈空间;(7)继续主调函数后续语句
8、。)继续主调函数后续语句。(5)释放被调函数中局部变量占用的栈空间;)释放被调函数中局部变量占用的栈空间;(4)执行被调函数函数体;)执行被调函数函数体;(3)为被调函数中的局部变量分配空间,完成参数传递;)为被调函数中的局部变量分配空间,完成参数传递;(2)保护现场:主调函数运行状态和返回地址入栈;)保护现场:主调函数运行状态和返回地址入栈;调用过程:调用过程:4.4 函数调用机制函数调用机制 void fun1(int,int);void fun2(float);int main()int x=1;y=2;fun1(x,y);return o;void fun1(int a,int b)f
9、loat x=3;fun2(x);void fun2(float y)int x;x栈顶栈顶栈底栈底y3fun2()fun1()运行状态及返回地址运行状态及返回地址x3b2a1fun1()main()运行状态及返回地址运行状态及返回地址y2x1main()操作系统运行状态及返回地址操作系统运行状态及返回地址此图例说明此图例说明在程序执行过程中怎样通过栈在程序执行过程中怎样通过栈“动态动态”地建立和地建立和释放局部变量占用的内存的释放局部变量占用的内存的 4.5 作用域与标识符的可见性作用域与标识符的可见性3 文件域文件域 2 函数声明域函数声明域 作作用用域域:指指标标识识符符能能够够被被使使
10、用用的的范范围围。只只有有在在作作用域内标识符才可以被访问(称为可见)。用域内标识符才可以被访问(称为可见)。本本节节重重点点讨讨论论局局部部域域和和文文件件域域(全全局局域域),其其中中局局部部域域包包括括块块域域和和函函数数声声明明域域。任任何何标标识识符符作作用用域域的的起始点均为起始点均为标识符说明标识符说明处。处。下面分别介绍下面分别介绍:1 块域块域 函函数数中中定定义义的的标标识识符符,包包括括形形参参和和函函数数体体中中定定义义的局部变量,作用域都在该函数内,也称作的局部变量,作用域都在该函数内,也称作函数域函数域。1.块域块域块块指指一一对对大大括括号号括括起起来来的的程程序
11、序段段。块块中中定定义义的的标标识符,作用域在块内。识符,作用域在块内。复合语句是一个块。复合语句是一个块。函数也是一个块。函数也是一个块。复合语句中定义的标识符,复合语句中定义的标识符,作用域仅在该复合语句中。作用域仅在该复合语句中。【例例4.7】输入两数,按从大到小的顺序保存。输入两数,按从大到小的顺序保存。块的引入:块的引入:1.块域块域【例例4.7】a=3 b=535a=3 b=5a=5 b=3【例例4.7】输入两数,按从大到小的顺序保存,并输出结果。输入两数,按从大到小的顺序保存,并输出结果。结果结果栈栈t=3 int main()int a,b;/具有函数域具有函数域 cout输入
12、两整数:输入两整数:ab;cout“a=atb=b=a)int t;/具有块域具有块域 t=a;a=b;b=t;/交换交换a,b的值的值 couta=atb=bendl;return 0;上述程序若在最后一个上述程序若在最后一个cout语句处增加:语句处增加:couttendl;则编译时会提示错误,因为变量则编译时会提示错误,因为变量t的作用域只在的作用域只在if语句中,其它地方语句中,其它地方不可见不可见。1.块域块域由由VC+运行,结果如下:运行,结果如下:输入两整数:输入两整数:3 5调用前:实参调用前:实参a=3,b=5调用中调用中交换前:形参交换前:形参a=3,b=5交换后:形参交换
13、后:形参a=5,b=3调用后:实参调用后:实参a=3,b=5 交换失败交换失败局部变量具有局部作用域使得程序在不同块中可以使用同名变量。局部变量具有局部作用域使得程序在不同块中可以使用同名变量。这些同名变量各自在自己的作用域中可见,在其它地方不可见这些同名变量各自在自己的作用域中可见,在其它地方不可见。【例例4.8】设计函数完成两数设计函数完成两数交换,用主函数进行测试。交换,用主函数进行测试。操作系统运行状态及返回地址操作系统运行状态及返回地址main()3a5bmain()运行状态及返回地址运行状态及返回地址swap()3a5b3t35【例例4.8】设计函数完成两数交换,用主函数进行测试。
14、设计函数完成两数交换,用主函数进行测试。#include void swap(int,int);int main()int a,b;/a,b作用域为作用域为main()cout输入两整数:输入两整数:ab;cout调用前:实参调用前:实参a=a,b=bendl;swap(a,b);/传值传值 cout调用后:实参调用后:实参a=a,b=bendl;return 0;void swap(int a,int b)/a,b作用域为作用域为swap()cout调用中调用中endl;cout交换前:形参交换前:形参a=a,b=bendl;int t;t=a;a=b;b=t;/交换交换swap()中的中的
15、a,b的值的值 cout交换后:形参交换后:形参a=a,b=bendl;1.块域块域 对于块中对于块中嵌套嵌套其它块的情况,如果嵌套块中有同其它块的情况,如果嵌套块中有同名局部变量,服从局部优先原则,即在内层块中名局部变量,服从局部优先原则,即在内层块中屏屏蔽蔽外层块中的同名变量,换句话说,内层块中局部外层块中的同名变量,换句话说,内层块中局部变量的作用域为内层块;外层块中局部变量的作用变量的作用域为内层块;外层块中局部变量的作用域为外层除去包含同名变量的内层块部分。域为外层除去包含同名变量的内层块部分。如果块内定义的局部变量与全局变量同名,块内仍如果块内定义的局部变量与全局变量同名,块内仍然
16、局部变量优先,但与块作用域不同的是,在块内然局部变量优先,但与块作用域不同的是,在块内可以通过域运算符可以通过域运算符“:”访问同名的全局变量。访问同名的全局变量。【例例4.9】显示同名变量可见性。显示同名变量可见性。全局全局n=100100 200 300内内 i=500内内 j=600内内n=500+600 =11001100 500 600100200+300=500500 500 200 300外部外部 i=200外部外部 j=300【例例4.9】显示同名变量可见性。显示同名变量可见性。int n=100;#include int main()int i=200,j=300;cout
17、ntitjendl;/内部块内部块 int i=500,j=600,n;n=i+j;cout ntitj endl;/输出局部变量输出局部变量n cout:nendl;/输出全局变量输出全局变量n n=i+j;/修改全局变量修改全局变量cout ntitj endl;return 0;2函数声明域函数声明域 函数声明不是定义函数,在作函数声明时,其中的形参作用域只在声明中,即作用域结束于右括号。正是由于形参不能被程序的其他地方引用,所以通常只要声明形参个数和类型,形参名可省略。3 3 文件域文件域 文文件件域域也也称称全全局局域域。定定义义在在所所有有函函数数之之外外的的标标识识符符作作用用域
18、域为为从从定定义义处处到到整整个个源源文文件件结结束束,即即文文件件域域 。文文件件中定义的全局变量和函数的作用域为文件域。中定义的全局变量和函数的作用域为文件域。如如果果某某个个文文件件中中说说明明了了作作用用域域为为文文件件域域的的标标识识符符,该该文文件件又又被被另另一一个个文文件件包包含含,则则该该标标识识符符的的作作用用域域延延伸伸到到新新的的文文件件中中。如如cincin和和coutcout是是在在头头文文件件iostreamiostream中中说说明明的的具具有有文文件件作作用用域域的的标标识识符符,它它们们的的作作用用域域也也延延伸伸到到嵌入嵌入iostreamiostream
19、的文件中。的文件中。存存储储类类型型(storage class)决决定定标标识识符符的的存存储储区区域域,即即编编译译系系统统在在不不同同区区域域为为不不同同存存储储类类型型的的标标识识符符分分配配空空间间。由由于于存存储储区区域域不不同同,标标识识符符的的生生命命期期也也不不同同。所所谓谓生生命命期期,指指的的是是标标识识符符从从获获得得空空间间到到空空间间释释放放之之间间的的期期间间,标标识识符符只只有有在在生生存存期期中中、并且在其自己的作用域中才能被访问。并且在其自己的作用域中才能被访问。4.6 存储类型与标识符的生命期存储类型与标识符的生命期 4.6.1 4.6.1 存储类型存储类
20、型存储类型存储类型 4.4.4.2 4.2 生命期生命期生命期生命期 自动变量为用自动变量为用auto说明的变量,通常说明的变量,通常auto缺省。局部变量都是自缺省。局部变量都是自动变量,生命期开始于块的执行,结束于块的结束,其原动变量,生命期开始于块的执行,结束于块的结束,其原因是自动变量的空间分配在栈中,块开始执行时系统自动因是自动变量的空间分配在栈中,块开始执行时系统自动分配空间,块执行结束时系统自动释放空间。故自动变量分配空间,块执行结束时系统自动释放空间。故自动变量的生命期和作用域是一致的。的生命期和作用域是一致的。4.6.1 存储类型存储类型 为为提提高高程程序序运运行行效效率率
21、,可可以以将将某某些些变变量量保保存存在在寄寄存存器器中中,即即用用register说明为寄存器变量,说明为寄存器变量,但不提倡使用但不提倡使用。C+中关于存储类型的说明符(中关于存储类型的说明符(storage class specifier)有四)有四个:个:auto、register、static和和extern。其中用。其中用auto和和register修修饰的称为自动存储类型,用饰的称为自动存储类型,用static修饰的称为静态存储类型,修饰的称为静态存储类型,用用extern修饰的称为外部存储类型。修饰的称为外部存储类型。1 1 自动存储类型自动存储类型static说说明明的的变变
22、量量称称为为静静态态变变量量。根根据据定定义义的的位位置置不不同同,还还分分为为局局部部静静态态变变量量和和全全局局静静态态变变量量,也也称称内内部部静静态态变变量量和和外外部部静静态态变变量量。静静态态变变量量均均存存储储在在全全局局数数据据区区,如如果果程程序序未未显显式式给给出出初初始始化化值值,则则等等效效初初始始化化为为全全0;静静态态变变量量占占有有的的空空间间要要到到整整个个程程序序执执行行结结束束才才释释放放,故故静静态态变变量量具具有有整整个个程程序序执执行行期期间间的的生命期。生命期。4.6.1 存储类型存储类型局局部部静静态态变变量量是是定定义义在在块块中中的的静静态态变
23、变量量,编编译译系系统统在在全全局局数数据据区区为为其其开开辟辟空空间间并并保保存存数数据据,该该空空间间一一直直到到整整个个程程序序结结束束才才释释放放。局局部部静静态态变变量量具具有有局局部部作作用用域域,但但却却具具有有整整个个程程序序执执行行期期间间的的生生命命期期。如如果果显显式式给给出出初初始始化化值值,则则在在该该块块第第一一次次执执行行时时完成,且只进行一次。完成,且只进行一次。2 2 2 2 静态存储类型静态存储类型静态存储类型静态存储类型【例例4.10】自动变量与局部静态变量的区别自动变量与局部静态变量的区别4.6.1 存储类型存储类型3 3 3 3 外部存储类型外部存储类
24、型外部存储类型外部存储类型一个一个C+程序可以由多个源程序文件组成。多文件程序系统可程序可以由多个源程序文件组成。多文件程序系统可以通过以通过外部存储类型外部存储类型的变量和函数来的变量和函数来共享共享某些数据和操作。某些数据和操作。在一个程序文件中定义的全局变量和函数缺省为外部的,即其作在一个程序文件中定义的全局变量和函数缺省为外部的,即其作用域可以延伸到程序的其他文件中。其他文件如果要使用这个文用域可以延伸到程序的其他文件中。其他文件如果要使用这个文件中定义的全局变量和函数,应该在使用前用件中定义的全局变量和函数,应该在使用前用“extern”作外部作外部声明。外部声明通常放在文件的开头(
25、声明。外部声明通常放在文件的开头(函数函数总是总是省略省略extern)。)。外部变量声明不同于全局变量定义,变量定义时编译器为其分外部变量声明不同于全局变量定义,变量定义时编译器为其分配存储空间,而变量声明则表示该全局变量已在其他地方定义配存储空间,而变量声明则表示该全局变量已在其他地方定义过,编译系统不再分配存储空间。过,编译系统不再分配存储空间。外部的全局变量或函数加上外部的全局变量或函数加上static修饰,就成为静态全局变量修饰,就成为静态全局变量或静态函数。静态的全局变量和函数作用域限制在本文件,其或静态函数。静态的全局变量和函数作用域限制在本文件,其他文件即使使用外部声明也无法使
26、用该全局变量或函数。他文件即使使用外部声明也无法使用该全局变量或函数。【例例4.11】外部存储类型的例子外部存储类型的例子4.6.2 生命期生命期1.1.静态生命期静态生命期 静态生命期静态生命期(Static extent或或Static storage duration)指)指的是标识符从程序开始运行时就存在,具有存储空间,到程的是标识符从程序开始运行时就存在,具有存储空间,到程序运行结束时消亡,释放存储空间。具有静态生命期的标识序运行结束时消亡,释放存储空间。具有静态生命期的标识符存放在全局数据区,如全局变量、静态全局变量、静态局符存放在全局数据区,如全局变量、静态全局变量、静态局部变量
27、。具有静态生命期的标识符在未被用户初始化的情况部变量。具有静态生命期的标识符在未被用户初始化的情况下,系统会下,系统会等效等效将其初始化为全将其初始化为全0。函数驻留在代码区,也具有静态生命期。所有具有文件函数驻留在代码区,也具有静态生命期。所有具有文件作用域的标识符都具有静态生命期。作用域的标识符都具有静态生命期。4.6.2 生命期生命期2.2.2.2.局部生命期局部生命期局部生命期局部生命期 在函数内部或块中定义的标识符具有在函数内部或块中定义的标识符具有局部生命期局部生命期(Automatic extent或或Automatic storage duration),),其生命期开始于执行
28、到该函数或块的标识符定义处,其生命期开始于执行到该函数或块的标识符定义处,结束于该函数或块的结束处。具有局部生命期的标识结束于该函数或块的结束处。具有局部生命期的标识符存放在栈区。具有局部生命期的标识符如果未被初符存放在栈区。具有局部生命期的标识符如果未被初始化,其内容是随机的,不可引用。始化,其内容是随机的,不可引用。具有局部生命期的标识符必定具有局部作用域;具有局部生命期的标识符必定具有局部作用域;但反之不然,静态局部变量具有局部作用域,但却具但反之不然,静态局部变量具有局部作用域,但却具有静态生命期。有静态生命期。4.6.2 生命期生命期具有具有动态生命期动态生命期(dynamic ex
29、tent或或dynamic storage duration)的标识符存放在自由存储区,)的标识符存放在自由存储区,由特定的函数调用或运算来创建和释放,如用由特定的函数调用或运算来创建和释放,如用new运算符(或调用运算符(或调用malloc()函数)为变量分配函数)为变量分配存储空间时,变量的生命期开始,而用存储空间时,变量的生命期开始,而用delete运运算符(或调用算符(或调用free()函数)释放空间或程序结束函数)释放空间或程序结束时,变量生命期结束。关于时,变量生命期结束。关于new运算符和运算符和delete运算符将在第七章中介绍。运算符将在第七章中介绍。4.4.动态生命期动态生命期