Download presentation
Presentation is loading. Please wait.
1
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第七章 作用域和存储属性 7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
2
7.1 C程序的结构 7.1.1 模块的概念: 模块 模块名 边界元素 函数 函数名 { } 类 类名 { } 一段源程序 源文件名
模块是指为完成特定的任务而建立的相对独立的程序单元。具体地说,是一段连续的,相邻的程序序列。它被边界元素“{ }”限制在一定的范围内,并有一个标识符从整体上代表这些程序语句序列。这个标识符就是此模块的名字,它可以被其它模块中的语句所引用。根据以上概念,可以被叫作模块的有: 模块 模块名 边界元素 函数 函数名 { } 类 类名 { } 一段源程序 源文件名 同一个源文件
3
7.1 C程序的结构 7.1.1 模块的概念(续): 图7-1-1显示了一个C语言程序结构,它由多个源程序模块(源文件)组成,一个源程序模块由一个或多个函数模块组成,程序从主函数模块开始执行,主函数模块调用其他函数模块,其他函数模块之间也可以相互调用,所有调用结束以后最终程序的执行流程要返回主函数模块。所以,一个可执行的C程序必须在某个源程序文件中,有且仅有一个主函数 图7-1-1 C语言的程序结构 … C程序(工程) 源程序文件1 源程序文件2 源程序文件n 预处理命令 数据声明 函数n 函数1
4
7.1 C程序的结构 7.1.2 模块与信息隐藏: 模块化的目的是为了隐藏信息。对一个模块而言,若它能被程序中的其它模块调用,则我们说:对调用它的模块而言,该模块可见。若模块内部的某些信息(函数,变量等)不被隐藏,则这部分就可被其它程序所引用。 作用域规则,访问控制及连接属性可将一个模块的信息隐藏或开放,从而在C程序的模块之间实现数据共享。
5
7.2 作用域和作用域规则 7.2.1 块作用域和局部变量: { 17 int k = stuNo[i] - ‘0’;
作用域 指的是程序正文中有效的那部分区域。具体而言,是程序正文中对象可以被使用的那部分区域。 7.2.1 块作用域和局部变量: 具有块作用域的对象是定义在一对{ }之内的。块作用域的范围从程序中对象定义处到块结束处的“}”止。具有块作用域的变量叫局部变量。 在程序7_1.cpp的第17行我们定义了一个局部变量k,其起作用的范围到程序第20行结束。所以,在第20行以后如果引用变量k,编译系统将会报错。也就是说,变量k仅在while循环内有效,超过这个范围,就不能使用此变量了。 { int k = stuNo[i] - ‘0’; number = 10 * number + k; i++; 20 }
6
7.2 作用域和作用域规则 7.2.2 函数作用域和形参变量: double average(int score[],int n)
作用域 指的是程序正文中有效的那部分区域。具体而言,是程序正文中对象可以被使用的那部分区域。 7.2.2 函数作用域和形参变量: 对象的函数作用域是指对象在定义它的整个函数的范围内都有效。C语言中,函数的形参变量具有函数作用域。 在程序7_2.cpp中,形参变量score和n的作用域为average函数开始处到average函数结束处。 double average(int score[],int n) { // average函数开始 int i = 0; …… } // average函数结束 void fun() { goto W1; … if(b>0) { W1:…; goto W2; } W2:…; 另外一个具有函数作用域的是goto XXX;语句中的语句标号 XXX。 即:该标号可以出现在一个函数体内的任何一条语句前。
7
7.2 作用域和作用域规则 7.2.3 文件作用域和全局变量:
作用域 指的是程序正文中有效的那部分区域。具体而言,是程序正文中对象可以被使用的那部分区域。 7.2.3 文件作用域和全局变量: 对象的文件作用域 是指从对象的定义处到整个源文件模块结束处。全局变量 是指定义在本源文件中所有函数之前的变量。其作用域从定义位置开始,直到程序结束。 C语言中,具有文件作用域的对象有全局变量和函数名(函数名就代表函数对象) 在7_3.cpp中定义了全局变量sum,其作用域为整个文件,因此,本文件的所有函数均可使用此变量。 int sum = 0;// 定义全局变量sum存放成绩总和 double average(int score[], int n) { …… } int main() { ……
8
7.2 作用域和作用域规则 小结 的作用范围 p,q a,b,c有效的范围 c1,c2 的作用范围 x,y,i,j有效的范围
int p=1,q=5; float f1(int a) { int b,c; …… } char c1,c2; char f2(int x,int y) { int i,j; main( ) { int m,n; 小结 的作用范围 p,q a,b,c有效的范围 c1,c2 的作用范围 x,y,i,j有效的范围 m,n有效的范围
9
7.2 作用域和作用域规则 对全局变量的使用,需要做如下说明:
例7.3 对全局变量的使用,需要做如下说明: ① 由于全局变量可以被同一源文件中的所有函数模块使用,因此全局变量提供了函数间除“实参—形参”相结合传送数据之外的另一种数据传送的渠道。实际应用中,函数调用时通过return语句只能返回一个值,而通过全局变量可以共享多个数据。 ② 由于全局变量在所有函数之前定义,同源文件中的所有函数都可以直接引用,不需另外说明。 ③ 使用全局变量时,如在一个函数中改变了全局变量的值,将影响到同源文件中的其他函数。实际应用中,有时在一个函数中不经意地改变全局变量的值,将使整个程序的运行出现错误。 ④ 全局变量使用过多,将降低程序的可读性,不便于分析每个全局变量的瞬时变化情况。另外全局变量的使用增强了函数之间的数据联系,但同时又使得函数过分依赖这些全局变量,降低了函数的独立性,因此从结构化程序设计的角度来讲,要限制全局变量的使用。
10
7.2 作用域和作用域规则 作用域 指的是程序正文中有效的那部分区域。具体而言,是程序正文中对象可以被使用的那部分区域。 作用域规则: 在一个源文件模块中,块作用域、函数作用域和文件作用域之间的包含关系如图7-2-1所示。 C语言的作用域需遵循以下规则: ① 内层作用域不能延伸到外层。 ② 在同一源文件中,若内层和外层中声明了同名标识符,则内层的标识符屏蔽外层的同名标识符。 ③ 在同一源文件中,如果内层想引用外层具有文件作用域的同名标识符(如同名的全局变量),在Visual Studio 2008编译环境下使用全局作用域运算符::。 ④ 如果要在一个源文件模块中引用另一个源文件模块中定义的全局变量,可使用关键字extern在使用它的源文件中进行引用性声明。参见教材P201 图7-2-1 作用域包含关系 文件作用域 函数作用域 块作用域 例7.4 例7.5
11
局部变量与全局变量小结: 局部变量 局部和全局是从变量的作用范围(空间上)划分的。 #include “stdio.h”
在一个块内定义的变量叫做局部变量。 局部变量只在定义它的块范围内有效,即程序只有在执行该块时才能访问这些变量,在执行其它函数时不能访问。 #include “stdio.h” void main( ) { int f; int n = 5; f = Fibo(n); printf(“f = %ld\n”, f); } n是main函数中的局部变量 f也是main函数中的局部变量
12
局部变量的有关说明 说明: 1.主函数之中定义的变量同样属于局部变量。其它函数不能访问主函数中的局部变量,主函数也不能访问其它函数中的局部变量。 2.不同函数中可以定义相同名字的变量。由于它们是各自函数内部的局部变量,所以互不影响。 3.形参变量也是局部变量。 4.在函数内部,还可以在复合语句(花括号括起的一组语句)内定义变量,这些变量只在该复合语句内起作用。
13
全局变量 全局变量 一个源程序文件中,在所有函数外定义的变量叫做全局变量。
全局变量的作用范围从定义的位置开始到该源程序文件结束。也就是说,在这个范围内,所有的函数都可以访问它(当然就可以改变它的值)。 全局变量的作用: 由于在全局变量的作用范围内,所有的函数都可以访问它,所以利用全局变量就可以在函数之间增加传递信息的通道。包括调用函数时传递信息进去,以及函数返回后得到多个返回值。
14
7.3 存储属性和生存期 7.3.1 变量的存储属性: (内存)用户区 现场断点,返回地址等
在C语言程序中使用的每个变量都具有两个属性:数据类型和存储类型。数据类型确定了变量在内存中分配的存储单元的多少,而存储类型决定了变量所分配的存储区的类型,而存储区的类型又决定了变量的生存期。所以,变量的存储类型决定了变量的生存期。由此可见,变量的存储类型是变量在时间方面的属性。 7.3.1 变量的存储属性: 在程序运行期间,该程序所占据的内存空间叫用户区。用户区又划分为: (内存)用户区 程序代码区 全局变量 静态数据存放区 静态局部变量 形参变量 动态数据存放区 自动变量 现场断点,返回地址等
15
7.3 存储属性和生存期 7.3.1 变量的存储属性(续): (内存)用户区 现场断点,返回地址等 程序代码区 全局变量
静态数据存放区 静态局部变量 形参变量 动态数据存放区 自动变量 现场断点,返回地址等 动态变量存放在动态数据存放区,动态数据存放区是由系统在程序运行期间根据需要动态分配的,需要时分配,不需要时释放。 静态变量存放在静态数据存放区,静态数据存放区一经分配,便要到程序运行结束后才会被释放。
16
7.3 存储属性和生存期 C语言中提供了4个关键字用于定义变量的存储类型,他们是:auto、extern、static和register。分别对应于四种存储类型:① 自动型;② 外部型;③ 静态型;④ 寄存器型。根据变量的存储类型,将变量分为四种类型的变量:① 自动变量(auto);② 外部变量(extern);③ 静态变量(static);④ 寄存器变量(register)。 7.3.2 自动变量: 自动变量的定义使用关键字auto。关键字auto可省略。 例 (auto) int a; 关键字auto一般可以缺省,本章以前函数内所定义的变量都是自动变量。 自动变量存放在内存的动态数据区,其作用域范围内的代码一旦执行完,这些变量的存储空间就释放了。 由于自动变量是内部变量,其作用域仅局限于它定义所在的模块内。
17
7.3 存储属性和生存期 7.3.3 外部变量: 外部变量的定义使用关键字extern。 例 extern int a;
例7.6 外部变量定义在所有函数之外,其作用域从它定义处到源文件结束处,具有文件作用域。 关键字extern一般可以缺省。 外部变量存放在内存的静态数据区。 在一个源文件中,如外部变量要在其定义之前使用,用关键字extern在使用它的函数中进行引用性声明。 显然,全局变量就是外部变量,二者的区别仅在于划分变量类别的角度不一样。实际上,全局变量和外部变量在使用上基本没有差别。所以,我们并未对二者进行严格的区分。
18
7.3 存储属性和生存期 7.3.4 静态变量: 静态变量的定义使用关键字static。 例 static int a;
例7.7 例7.8 根据变量的作用域的不同,静态变量可分为静态局部变量和静态全局变量。 函数内定义的静态变量为静态局部变量。 静态局部变量的作用域同自动变量,两者区别在于生存期的不同。在整个程序的运行过程中,静态局部变量一直存在。 静态局部变量能保留上次调用时的值。 静态局部变量在编译时赋初值,即只赋初值1次。如果程序中没有给静态局部变量显示赋初值,则编译时,系统自动赋初值0(对数值型变量)或空字符(字符型变量) 如果变量初始化后,只被引用而不需要改变其值,则该变量定义为静态局部变量比较好。
19
7.3 存储属性和生存期 7.3.4 静态变量(续): 静态变量的定义使用关键字static。 例 static int a;
根据变量的作用域的不同,静态变量可分为静态局部变量 和静态全局变量。 全局变量和静态全局变量的存储方式均为静态存储方式,两者的区别在于作用域的不同。 静态全局变量作用域为其所在的源程序文件,即只能被该源程序中的函数使用; 全局变量可以通过关键字extern将作用域扩展到其他源程序文件。 例7.9
20
7.3 存储属性和生存期 7.3.5 寄存器变量: 寄存器变量的定义使用关键字register。 例 register int i,j,k;
寄存器变量存放在寄存器中,主要是一些使用频繁的变量。 只有内部变量和形参变量可以定义为寄存器变量。 函数调用时为定义为寄存器变量的形参变量分配寄存器,调用结束后就释放所分配的寄存器。 寄存器变量是内部变量,其作用域为块作用域或函数作用域,其生命期为函数的每次调用。 例7.10
21
作用域和生存期的小结 文件作用域中定义的对象(全局变量)具有静态生存期。即在程序执行过程中它们占据固定的存储单元一直到程序结束。
函数作用域和块作用域中定义的对象(局部变量)具有动态生存期。即在程序执行过程中它们所占据的存储单元是动态地进行分配和释放。 函数作用域和块作用域中定义的对象要具有静态生存期必需在其定义时加关键字static(声明为静态局部变量)
22
static和extern关键字的小结 static 关键字用在局部变量定义时,是将该动态局部变量变为静态局部变量;
23
7.4 变量的初始化 7.4.1 内部变量的初始化: 7.4.2 外部变量的初始化:
这里的内部变量指自动变量。自动变量的初始化是在函数调用时进行的,每调用一次函数都将重新进行一次初始化。 如果定义自动变量时未进行初始化,或自动变量未被赋值,则其值将不确定,这将引起一个错误的结果,在程序设计中应注意避免。 外部变量的初始化: 外部变量可以被本源程序文件中其他函数使用,其作用域从其定义的位置开始,一直到本源程序结束。 外部变量在程序执行过程中,占有固定的存储单元,其生存期为整个程序。 在定义外部变量时,如未进行初始化,则数值型外部变量的值缺省为0,字符型外部变量的值缺省为字符'\0'。
24
7.4 变量的初始化 7.4.3 静态变量的初始化: 7.4.4 寄存器变量的初始化: 例7.11
静态变量,不管是静态全局变量,还是静态局部变量,都是在编译时,系统分配固定的存储单元,并始终存在,直到源程序运行结束。 如在定义静态变量时进行初始化,则静态变量只在第一次使用时被赋初值。如未进行初始化,则数值型静态变量的缺省值为0,字符型静态变量的缺省值为字符'\0'。 寄存器变量的初始化: 寄存器变量作用域同局部变量,函数调用结束后,寄存器变量的存储空间被释放。 寄存器变量的初始化是在函数调用时进行的,如未进行初始化,其值将不确定,这一点与自动变量相同。
25
7.5 应用举例 例7.11
26
第7章作业: 7.1题、 7.2题、 7.6题、 7.7题、
Similar presentations