静态变量详解

来源:互联网 发布:java 断点 编译后 存在 编辑:程序博客网 时间:2024/06/14 21:13

先看一个程序吧。

#include "stdafx.h"#include "stdio.h"#include "iostream.h"int fun1(){ static int a1 = 5; a1++; return a1;}int fun2(){ static int a1 = 5; int a2 = 5; a2++; return a2;}int main(int argc, char* argv[]){ cout<<fun1()<<endl; cout<<fun1()<<endl; cout<<fun1()<<endl; cout<<fun1()<<endl; cout<<fun1()<<endl; cout<<fun1()<<endl; cout<<endl; cout<<fun2()<<endl; cout<<fun2()<<endl; cout<<fun2()<<endl; cout<<fun2()<<endl; cout<<fun2()<<endl; cout<<fun2()<<endl; cout<<endl; return 0;}


大部分人都能分析出fun1会输出5 6 7 8 9 10 而fun2会一直输出 6 6 6 6 6 6.
这里面就牵涉到了静态变量相关的知识,fun1在第一次调用时,会将变量a1存放于静态数据区,并赋初值5,当第二次调用static int a1 = 5;时,编译器会首先检查静态存储是否有变量a1,如果有就直接取静态数据区的值,static int a1 = 5;赋值部分便不再执行。(这样解释不是很权威,当初编译原理没弄好。)

      静态变量是静态存储方式,但是属于静态存储方式的量不一定就是静态变量, 例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。 对于自动变量,它属于动态存储方式。 但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。
    静态变量与程序有着相同生命周期;因此上面的程序中,a1变量一直存活着,直到main函数退出。其实在fun2中也可以再重新定义 static int a1 = 5; fun2中的a1生命周期同样跟整个程序的生命周期相同,但是fun1和fun2中这两个变量的作用域不同。也就是说在fun1中是看不到fun2中定义的a1,同样fun2中也看不到fun1中定义的a1.
      静态局部变量属于静态存储方式,它具有以下特点:
(1)静态局部变量在函数内定义,但不象自动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。
(2)静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
(3)允许对构造类静态局部量赋初值。若未赋以初值,则由系统自动赋值。数值型变量自动赋初值0,字符型变量赋空字符。
(4)对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。 根据静态局部变量的特点, 可以看出它是一种生存期为整个源文件的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。
    全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。
    将变量声明为static存储类还会根据变量属性不同而有一些特殊的作用:
对于静态全局变量来说,针对某一源文件的以static声明的文件级变量与函数的作用域只限于文件内(只在文件内可见),也即“内部连接”,因而可以用来限定变量的作用域;
对于静态局部变量来说,在函数内以static声明的变量虽然与自动局部变量的作用域相同(即作用域都只限于函数内),但存储空间是以静态分配而非默认的自动分配方式获取的,因而存储空间所在区域不同(一般来说,静态分配时存储空间于编译时在程序数据段分配,一次分配全程有效;而自动分配时存储空间则是于调用栈上分配,只在调用时分配与释放),且两次调用间变量值始终保持一致;

0 0
原创粉丝点击