静态变量,全局变量,常量辨析

首先理解生存周期作用域的区别:

  • 生存周期: 变量从定义到销毁的时间范围。存放在全局数据区的变量的生存周期存在于整个程序运行期间,而存放在栈中的数据则随着函数等的作用域结束导致出栈而销毁,除了静态变量之外的局部变量都存放于栈中。
  • 作用域: 变量的可见代码域(块作用域,函数作用域,类作用域,程序全局作用域)。

static变量是指静态的变量,不管是在全局还是局部声明的static变量都存放于程序的全局变量区域,所以它的生命周期是从程序开始到程序结束。但是static变量的作用域并不等同于它的生存周期,它的作用域决定于它被定义的位置。可以认为static变量的作用域<=生存周期。

补充:
内存分配区域:
BSS段 :通常是指用来存放程序中未初始化的全局变量、静态变量(全局变量未初始化时默认为0)的一块内存区域
数据段 :通常是指用来存放程序中 初始化后的全局变量和静态变量
代码段 :通常是指用来存放程序中 代码和常量
:通常是指用来存放程序中进程运行时被动态分配的内存段 ( 动态分配:malloc / new,者动态释放:free / delete)
:通常是指用来存放程序中用户临时创建的局部变量、函数形参、数组(局部变量未初始化则默认为垃圾值)也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进后出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。它是由操作系统分配的,内存的申请与回收都由OS管理。

1. 静态全局变量普通全局变量的区别 ?
全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式,因此这两者在存储方式上并无不同
这两者的区别在于其作用域不同,
①普通全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,普通全局变量在各个源文件中都是有效的。
②而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
static全局变量只初使化一次,防止在其他文件单元中被引用。

2. 静态局部变量普通局部变量的区别
生命周期不同。函数内部的静态局部变量只经历一次的创建和初始化,函数执行完不死亡,后续再次调用会用上一次的值。而局部变量每次调用都会重新创建和初始化,函数结束时死亡。
把局部变量改变为静态变量后是改变了它的存储方式(栈->代码段)和生存期(函数结束->程序结束)。
把全局变量改变为静态变量后是改变了它的作用域,限制了它的作用域。

3.静态局部变量全局变量的区别
①静态局部变量所在的函数在多调用多次时,只有第一次才经历变量定义和初始化,以后多次在调用时不再定义和初始化,而是维持之前上一次调用时执行后这个变量的值。本次接着来使用。
②静态局部变量在第一次函数被调用时创造并初始化,但在函数退出时它不死亡,而是保持其值等待函数下一次被调用。下次调用时不再重新创造和初始化该变量,而是直接用上一次留下的值为基础来进行操作。
③静态局部变量的这种特性,和全局变量非常类似。它们的相同点是都创造和初始化一次,以后调用时值保持上次的不变。不同点在于作用域不同

4.局部变量全局变量的对比:
①定义同时没有初始化,则局部变量的值是随机的,而全局变量的值是默认为0.
②使用范围上:全局变量具有文件作用域,而局部变量只有代码块作用域。
③生命周期上:全局变量是在程序开始运行之前的初始化阶段就诞生,到整个程序结束退出的时候才死亡;而局部变量在进入局部变量所在的代码块时诞生,在该代码块退出的时候死亡。
④变量分配位置:全局变量分配在数据段上,而局部变量分配在栈上。

5. 静态函数普通函数的区别?
①静态函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static修饰的函数),内部函数应该在当前源文件中说明和定义。而普通函数可以再其他文件中调用,只需要在其他文件中的头文件中说明包含此函数的源文件。
②static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。

6. 常量静态变量区别
①常量本身就是值的形式,内存中是不分空间的
②而静态变量,是变量形式,内存中是要分空间的

举一个局部声明的例子。在函数test中声明静态变量i:

void test() 
{ 
	int m=3; 
	static int i=5; 
} 

局部变量m存放在栈中,当test函数结束,m将被销毁;静态变量i不存放在栈中,而是存放于程序的全局变量区域,因此随着函数test的结束,它并不随着出栈操作而被销毁,它的生存周期存在于程序的整个运行期;然而m和i的作用域都仅存在于test函数中它们的定义之后,即test调用结束之后,m和i就不再可用,但是i仍存在于内存之中。

再举一个全局声明的例子。在文件A 中定义静态变量j:

int n=3; //默认为extern 
static int j=5; //声明为static 

全局变量和静态变量j都存放于程序的全局数据区域,它们的生存周期都是程序的整个运行期,但是n的作用域为全局作用域,可以通过extern在其他文件中使用,而j只能在文件A中使用,例如在文件B中:

extern int n; //ok 
extern int j; //error: j在文件B中不可见 
int a=n;//ok:但这里有个初始化先后的问题,具体参见参考一 
int b=j;//error 

也就是说,在声明全局的static变量时,static没有改变它的生存周期,也即存储位置(因为全局变量本来就存储在全局数据域),而是将变量的作用域限制在当前文件中。

参考:
https://blog.csdn.net/weixin_41931540/article/details/91348061
https://www.cnblogs.com/bigclould/p/9322248.html
https://blog.csdn.net/qq_40945965/article/details/79082792

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值