当前课程知识点:C语言程序设计 > 第8章 函数 > 8.4 变量的作用域和生存期 > 变量的作用域和生存期
同学们大家好我们今天讲的内容是变量的作用域和生存期
首先来看变量的作用域和生存期的基本概念
变量的作用域指的是变量的作用范围
或有效范围
表现为变量有的可以在整个程序或其它程序中进行引用
有的则只能在局部范围内引用
按其作用域范围可分为两种
即局部变量和全局变量
变量的生存期
指的是变量从被生成到被撤消的这段时间
实际上就是变量占用内存的时间
变量按其生存期可分为两种
即动态变量和静态变量
变量只能在其生存期内被引用
变量的作用域直接影响变量的生存期
作用域和生存期是从空间和时间的角度来体现变量的特性
下面看局部变量的生存期
首先来看什么是局部变量
局部变量指的是在函数内作定义说明的变量
其作用域
仅限于函数内
离开函数后不可再引用
即不能在一个函数外去引用一个函数内部定义的变量
局部变量的生存期
是从函数被调用的开始到函数调用结束
即在这个期间局部变量都会占用内存
局部变量在函数调用时被分配内存
而当函数调用结束局部变量占用的内存将会被释放
例如
这个例子中的f1函数中定义了局部变量z
其作用范围就只能是在f1函数中
而如果在函数f2中引用z
就会产生引用错误
有一下几点需要说明
第一主函数main( )中定义的变量也是局部变量
它只能在主函数中使用
其它函数不能使用
同时主函数中也不能使用其它函数中定义的局部变量
例如 这个例子中
main函数中引用f3函数中定义的局部变量y
以及f3函数引用main函数中定义的局部变量a
都是错误的
形参变量属于被调函数的局部变量
实参变量则属于全局变量或主调函数的局部变量
第三 允许在不同的函数中使用相同的变量名
它们代表不同的对象
分配不同的单元
互不干扰 也不会发生混淆
例如这个例子中
main函数中定义了局部变量a和b
而在subf函数中
也定义了同名的变量a和b
这并不会产生问题
它们之间也相互不干扰
main函数调用subf函数时
输出了subf函数中的a和b即6 和 7
而main函数调用subf函数前后
分别输出了main函数中的a和b即3 和 4
它们之间相互不干扰
第四在复合语句中定义的变量也是局部变量
其作用域只在复合语句范围内
其生存期是从复合语句被
被执行的时刻到复合语句执行完毕的时刻
例如这个例子中
main函数中定了局部变量b
而在复合语句中也定义了局部变量b
这是允许的
但在复合语句中使用b
将会使用复合语句中定义的局部变量b
复合语句中可以引用它所属函数中定义的局部变量
例如
复合语句中引用main函数中定义的局部变量a
但要注意
复合语句中定义的局部变量
只能在复合语句中使用
例如
main函数在复合语句外
使用复合语句中定义的局部变量k
将会产生错误
下面我们学习全局变量作用域和生存期
那么什么是全局变量呢
全局变量又叫外部变量
指的是在函数外部作定义说明的变量
也称为外部变量全局变量不属于哪一个函数
而是属于一个源程序文件
全局变量的作用域
是从定义变量的位置开始到本源文件结束
及有extern说明的其它源文件
全局变量的生存期 与程序相同
即从程序开始执行到程序终止的这段时间内
全局变量都有效
例如这个例子中定义了全局变量n
它的值在main函数中由用户输入
自定义函数sqr函数计算全局变量n的平方根
但由于n的作用域是从其定义位置到源文件结尾
而这个定义位置又在sqr函数引用n的位置之后
所有导致sqr函数无法引用n
正确的做法是
将float n=0这个全局变量定义语句
放在源文件的开头或第3行
即头文件包含语句的后面
那么就不会发生引用错误
这里对全局变量需要说明几点
第一应尽量少使用全局变量
因为首先全局变量在程序全部执行过程中
始终占用存储单元
其次局变量降低了函数的独立性
通用性可靠性及可移植性
再次全局变量降低了程序清晰性
容易出错 第二
第二若外部变量与局部变量同名
则外部变量被屏蔽
要引用全局变量
则必须在变量名前家上两个冒号::
例如
这个例子中
main函数定义了一个与全局变量a同名的局部变量a
那么在main函数中使用a时
将会使用局部变量a
若想引用全局变量a
则应加两个冒号::
例如程序的最后一行
输出了全局变量a
第三 全局变量定义必须在所有的函数之外
且只能定义一次
不可重复定义
并可赋初始值
全局变量定义的一般形式为
[extern] 关键字这个方框号表示的含义是
[extern] 关键字是可以省略的
然后类型说明符 全局变量名1[ = 初始值1]
…… 全局变量名n[ = 初始值n]
其中extern关键字是可以省略的
而且通常省略
例如int a = 2b = 4
等价于 extern int a = 2
b = 4
第四 对全局变量进行说明
可扩展全局变量的作用域
全局变量说明的一般形式为
extern 类型说明符 全局变量名1
…全局变量名n
例如这个例子中
在gy函数之前定义了全局变量x和y
其作用域如图红色箭头所示
当我们在gx函数之前增加了语句extern int xy;
后xy的作用域便被扩展了
当我们在main函数中增加了语句extern int xy后
则xy的作用域便被扩展到了main函数之中
这就是extern关键字对全局变量的声明
第五全局变量定义与全局变量的说明的区分
举例说明
在这个例子当中
上面的extern int a和下面的extern int a=2
这两条语句
哪一个是全局变量的定义
哪一个是说明呢
我们说
下面的语句extern int a=2是定义
而上面的语句extern int a是说明
因为下面的语句赋了初值
注意
两者中有且只能有一个对变量a赋初始值
不能都对变量a赋初始值或都不赋值
否则编译将会出错
好同学们今天的内容就讲到这里
我们下次再见
-计算思维与计算机
--计算思维与计算机
--计算思维与计算机
--计算思维和计算机
-2.1 程序设计语言的发展及其特点和应用
--程序设计语言的特点及发展
- 2.2 C语言程序的基本结构及编制C语言程序的基本步骤
--C语言程序的结构和编制步骤
-3.1 C语言的数据类型
--C语言的数据类型
--C语言的数据类型
-3.2 常量
--常量
--常量
-3.3 什么是变量
--什么是变量
--什么是变量
-3.4 如何进行算术运算
--如何进行算术运算
--如何进行算术运算
-3.5 赋值运算符和逗号运算符
--赋值运算符和逗号运算符
-3.6 数据类型转换
--数据类型转换
--数据类型转换
-4.1 格式化输出printf
--格式化输出
-4.2 格式化输入scanf及字符数据的非格式化输入输出
--格式化输入
-5.1 关系运算符和关系表达式
--关系运算符和关系表达式
-5.2 逻辑运算符和逻辑表达式
--逻辑运算符和逻辑表达式
-5.3 条件运算符和条件表达式
--条件运算符和条件表达式
-5.4 if语句
--if语句
--if语句
-5.5 switch语句
--switch语句
--switch语句
-6.1 while语句
--while语句
--while语句
--do-while语句
-6.2 for语句
--for语句
--for语句
-6.3 循环的嵌套
--循环的嵌套
--循环的嵌套
-6.4 break语句和continue语句
--break和continue语句
-7.1 一维数组的定义和引用
--一维数组的定义和引用
-7.2 一维数组的赋值
--一维数组的赋值
--一维数组的赋值
-7.3 二维数组的定义和引用
--二维数组的定义和引用
-7.4 二维数组的赋值
--二维数组的赋值
--二维数组的赋值
-7.5 字符串的本质
--字符串的本质
--字符串的本质
-7.6 字符串操作的常用函数
--字符串常用函数
-7.7 字符串数组
--字符串数组
--字符串数组
-8.1 函数概述
--函数概述
--函数概述
-8.2 有参函数
--有参函数
--有参函数
-8.3 函数参数的传递方式
--函数参数的传递方式
-8.4 变量的作用域和生存期
--变量的作用域和生存期
-8.5 变量的存储类型
--变量的存储类型
--变量的存储类型
-8.6 函数的嵌套和递归调用
--函数的嵌套和递归调用
-8.7 函数的作用域与封装
--函数的作用域与封装
-9.1 指针变量的概念(上)
--指针变量的概念(上)
-9.2 指针变量的概念(下)
--指针变量的概念(下)
-9.3 指向一维数组的指针变量
--指向一维数组的指针变量
-9.4 指向二维数组的指针变量(上)
--指向二维数组的指针变量(上)
-9.5 指向二维数组的指针变量(下)
--指向二维数组的指针变量(下)
-9.6 动态内存分配
--动态内存分配
--动态内存分配
-10.1 编译预处理
--编译预处理
-11.1 用户自己建立数据类型
--用户自己建立数据类型
-11.2 定义结构体类型变量
--定义结构体类型变量
-11.3 结构体变量的引用与初始化
-11.4 结构体数组
--结构体数组
--结构体数组
-11.5 指向结构体类型数据的指针
--指向结构体类型数据的指针
-12.1 文件的基本概念和文件指针
--文件的基本概念和文件指针
-12,2 文件的打开和关闭
--文件的打开和关闭
--文件的打开和关闭
-12.3 文本文件读写
--文本文件读写
--文本文件读写
-12.4 二进制文件读写
--二进制文件读写
--二进制文件读写