全局变量与静态全局变量的异同

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

static变量是指静态的变量,无论是在全局仍是局部声明的static变量都存放于程序的全局变量区域,因此它的生命周期是从程序开始到程序结束。可是static变量的做用域并不等同于它的生存周期,它的做用域决定于它被定义的位置。能够认为static变量的做用域<=生存周期。.net

举一个局部声明的例子。在函数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没有改变它的生存周期,也即存储位置(由于全局变量原本就存储在全局数据域),而是将变量的做用域限制在当前文件中。blog

中兴通信2012校招笔试题的一道问答题: 
1. static全局变量与普通的全局变量有什么区别 ? 
 全局变量(外部变量)的说明以前再冠以static 就构成了静态的全局变量。 
  全局变量自己就是静态存储方式, 静态全局变量固然也是静态存储方式。 这二者在存储方式上并没有不一样。 
  这二者的区别在于非静态全局变量的做用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其做用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。因为静态全局变量的做用域局限于一个源文件内,只能为该源文件内的函数公用,所以能够避免在其它源文件中引发错误。 
static全局变量只初使化一次,防止在其余文件单元中被引用;   
2. static局部变量和普通局部变量有什么区别 ? 
  把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的做用域,限制了它的使用范围。 
  static局部变量只被初始化一次,下一次依据上一次结果值;   
3. static函数与普通函数有什么区别? 
   static函数与普通函数做用域不一样,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static修饰的函数),内部函数应该在当前源文件中说明和定义。对于可在当前源文件之外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件. 
static函数在内存中只有一份,普通函数在每一个被调用中维持一份拷贝生命周期

P.S. 
C程序一直由下列部分组成: 
1)正文段(代码段)——CPU执行的机器指令部分;一个程序只有一个副本;只读,防止程序因为意外事故而修改自身指令; 
2)初始化数据段(数据段)——在程序中全部赋了初值的全局变量,存放在这里。 
3)非初始化数据段(bss段)——在程序中没有初始化的全局变量;内核将此段初始化为0。(这就是为何全局内置类型变量会初始化,而局部变量就为未初始化的未知值) 
4)栈——增加方向:自顶向下增加;自动变量以及每次函数调用时所须要保存的信息(返回地址;环境信息)。 
5)堆——动态存储分。 
程序在内存中申请了代码段,全局数据段(初始化和未初始化),栈和堆:程序代码放于代码段,全局变量和静态变量存放在全局数据段中,一直存在直到程序结束,而局部变量都放于临时的栈中,随着做用域的结束随着出栈操做而销毁。malloc和new出来的内存不属于上面提到的程序申请的内存中,而是在系统中申请到的内存,因此若是在程序中没有明确free和delete的话,程序结束后该内存仍不会被释放,形成内存泄漏。例如: 
int test() 

int * p=new int(3); 

则test函数结束后,p指针自己被销毁,由于它是存在于函数栈中的局部变量,而p指向的int整型内容仍存在于内容堆中,没有被释放,形成内存泄漏。 
详细内存使用和参考http://blog.csdn.net/cc198877/article/details/8849694内存

相关文章
相关标签/搜索