生存期作用域与可见域精.ppt
《生存期作用域与可见域精.ppt》由会员分享,可在线阅读,更多相关《生存期作用域与可见域精.ppt(33页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、生存期作用域与可见域第1页,本讲稿共33页19.1 内存分配变量名、函数名等都对应着内存中的一块区域,那这些实体在内存中是如何存放的呢,程序又是如何使用这些变量的,首先从C程序内存分配入手,一步步回答这些问题。第2页,本讲稿共33页19.1.1 内存分区一个由C编译的程序占用的内存大致分为以下几部分:栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等。堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回收。全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初
2、始化的全局变量和未初始化的静态变量在相邻的另一块区域,该区域在程序结束后由操作系统释放。常量区:字符串常量和其他常量的存储位置,程序结束后由操作系统释放。程序代码区:存放函数体的二进制代码。第3页,本讲稿共33页19.1.2 变量的存储类别C语言中,变量的存储类别大致分为4种:auto(自动)、register(寄存器)、static(静态)和extern(外部)。其中,auto和register变量属于自动分配方式,而static和extern变量属于静态分配方式。不同分配方式下,变量的生存期、作用域和可见域各不相同。按作用域分,变量可分为局部变量和全局变量,所谓局部变量,是指在函数内部定义
3、的变量,局部变量仅在定义它的函数内才能有效使用,其作用域仅限在函数内,即从变量定义的位置开始,到函数体结束。通常,编译器不为局部变量分配内存单元,而是在程序运行中,当局部变量所在的函数被调用时,系统根据需要临时为其分配内存。当函数执行结束时,局部变量被撤销,占用内存被收回。在函数外定义的变量称为全局变量,也称外部变量,全局变量的作用域较广,全局变量不属于任何一个函数,理论上可被其作用域中的所有函数访问,因此,提供了一个不同函数间联系的途径,使函数间的数据联系不只局限于参数传递和return语句。全局变量一经定义,编译器会为其分配固定的内存单元,在程序运行期间,这块内存单元始终有效,一直到程序执
4、行完毕才由操作系统收回该块内存。第4页,本讲稿共33页19.1.3 生存期通俗地讲:生存期指的是在程序运行过程中,变量从创建到撤销的一段时间。生存期的长短取决于前面所讲的存储方式,对于自动分配(栈分配),变量与其所在的代码块共存亡;对于静态分配(编译器预分配),变量与程序共存亡,程序开始执行时即已存在,一致到程序运行完毕退出后才撤销;对于动态存储的内存块(注意:不是指向该内存块的指针),由程序员决定其生存期。对程序代码区的函数、常量区的字符串常量和其他常量等、结构体和共用体的定义等来说,生存期的讨论没有意义,因为它们都是与程序共存亡的。第5页,本讲稿共33页19.1.4 作用域与可见域在程序代
5、码中,变量有效的范围(源程序区域)称为作用域,能对变量、标识符进行合法的访问的范围(源程序区域)称为可见域,可以这样说,作用域是变量理论上有效的区域,而可见域是变量实际有效的区域,可见域是作用域的子集。可以将C语言的作用域分为以下几类:(1)块作用域自动变量(auto、register)和内部静态变量(static)具有块作用域,在一个块内声明的变量,其作用域从声明点开始,到该块结束为止。函数定义中声明的形参,其作用域限定在该函数体内,与其他函数中声明的同名变量不是一回事,允许在不同的函数中使用相同的变量名,编译器将为这些变量分配不同的存储单元,不会混淆。(2)文件作用域外部静态变量(stat
6、ic)具有文件作用域,从声明点开始到文件末尾,此处所指的文件是编译基本单位c文件。(3)全局(程序)作用域全局变量(extern)具有全局作用域,只要在使用前对其进行声明,便可在程序(由若干个文件组成)的任意位置使用全局变量。第6页,本讲稿共33页19.2 auto变量函数的形参及代码块中定义的变量都属于auto变量,这是C语言中应用最广的一种变量,这类变量是栈分配的,是动态分配存储空间的。举函数形参为例,当调用该函数时,为形参分配存储空间,当函数调用结束时,就自动释放这些存储空间。对代码块中定义的变量(包含函数中定义的变量),当执行到变量声明语句时,系统为这些auto变量分配空间,当程序流程
7、离开代码块时,这些变量被自动撤销,其占用的内存空间被释放。第7页,本讲稿共33页19.2.1 定义格式自动变量的定义格式为auto 数据类型 变量1=初始化表达式,变量2=初始化表达式;其中,方括号表示可以省略,此处变量不仅指普通内置类型的变量,还包括数组、结构体和指针等复合结构。C语言默认所定义的变量是auto变量,在以前所举例子中,函数和代码块中的局部变量并没有使用关键字auto,这实际上是遵循了C语言的默认规定,举个例子来说,在一个函数中,如下定义:int a;float b:自动被C编译器解释为:auto int a;auto float b;第8页,本讲稿共33页19.2.2 作用域
8、和生存期auto变量的作用域和生存期都局限在定义它的代码块中,所谓代码块,是指用两个花括号包裹起来的代码行,函数只是代码块的一种,常见的代码块还有if结构、for结构等等,哪怕只是两个成对花括号,也能构成一个独立代码块。此外,结合“先声明,后使用”的原则,可知,auto变量的作用域和生存期对应着从定义到所在代码块结束这块时空区域。来看下面的函数:1int func(int m,int n)23int x;/*等价于auto int x;*/45int a,b,c;/*等价于auto int a,b,c;*/678int y,z;/*等价于auto int y,z;*/910return 0;1
9、1第9页,本讲稿共33页19.2.3 屏蔽代码块可以嵌套应用形成一定的层次结构,那内外层代码块中可否定义同名变量呢?如果可以,这些同名变量有什么关系呢?先来看一段示例:第10页,本讲稿共33页19.2.4 重复定义auto变量不能重复定义,所谓重复,是指在同一代码块中,出现两个同名变量。此处所指的同一代码块,不包括屏蔽的情况。下面的代码就犯了重复定义的错误:if()int x,y;double x,y;并列层次的代码块中可以出现同名变量而不会引起混淆,最普遍的一个例子就是函数,由于所有的函数都是在外部定义的,包括main函数在内的所有函数都是并列的,因此,函数A内定义的auto变量在函数B内是
10、完全不可见的,即使两个函数中定义了同名变量,编译器也能很好地将其区分开,这大大方便了函数的编写。第11页,本讲稿共33页19.2.5 初始化编译器并不会自动为auto变量初始化,这项工作必须在变量定义时由程序员显式完成,否则,变量的值是随机不确定的。不论是指针还是普通变量,时刻提醒自己注意初始化,能有效防止一些稀奇古怪错误的发生。第12页,本讲稿共33页19.3 register变量一般来说,CPU访问内部寄存器的速度大大高于访问内存的速度,因此,有人提议,能否将一些应用频繁的变量放在CPU的通用寄存器中,这样,在使用该变量时便不必再访问内存,直接从寄存器中取,将大大提高程序运行的效率,因此,
11、C语言引入了register变量,称为寄存器变量。第13页,本讲稿共33页19.3.1 定义格式寄存器变量的定义格式为:register 数据类型 变量1=初始化表达式,变量2=初始化表达式;和auto变量一样,register变量也属于局部变量。只能在函数体内定义register变量,CPU使用寄存器中数据的速度要远远快于使用内存中的数据速度,因此,应用好CPU内的寄存器可以大大提高程序的运行效率和速度。但是,CPU中寄存器的数量有限,所以,通常是把使用频繁的变量定义为寄存器变量。第14页,本讲稿共33页19.3.2 使用举例来看一个计算的近似值的例子,求解的一个近似公式如下:为了达到较高精
12、度,需要进行的循环次数较多,为提高效率,可将循环控制变量定义为寄存器变量,如所示:第15页,本讲稿共33页19.4 extern变量extern变量又称全局变量,放在静态存储区,所谓全局,是说该变量可以在程序的任意位置使用,其作用域是整个程序代码范围内,和auto变量不同的是,extern变量有定义和声明之分。第16页,本讲稿共33页19.4.1 全局变量定义全局变量定义的基本格式为:extern 类型 变量名=初始化表达式;此时,初始化表达式不可省略,此指令通知编译器在静态存储区中开辟一块指定类型大小的内存区域,用于存储该变量。下列语句创建了一个初始值为100的int型全局变量m:exter
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 生存 作用 可见
限制150内