静态变量

静态变量（）在计算机编程领域指在程序执行前系统就为其進行記憶體分配（也即在运行时中不再改变分配情况）存储空间的一类变量。与之相对应的是在运行时只暂时存在的自动变量（即局部变量）与以动态分配方式获取存储空间的一些对象，其中自动变量的存储空间在调用栈上分配与释放。

概念与定义

“静态变量”这一术语有两个容易混淆的定义：

语言无关的通用定义：与程序有着相同的变量；
C族语言特有的定义：以static存储类声明的变量。

而在以Pascal为代表的许多程序语言中，所有局部变量都由系统自动分配存储空间，而所有全局变量的存储空间则以静态分配的方式获取（对应“静态变量”），因此由于实际上“局部变量”和“全局变量”这两个术语已足以涵盖所有的情况，在这些程序语言中通常不使用“静态变量”这一术语，而直接以“全局变量”代之。一般来说，在这些程序语言中，静态变量就是全局变量，而即使在有明确区分全局和静态变量的程序语言中，在编译后的代码里二者也以相同的方式获取存储空间。而今术语“静态变量”的概念则主要基于C族语言的“static”的定义（即定义2）。

作常量使用

静态变量也可以用于存储常数。具体来说，静态变量（全局变量及汇编语言里定义的符号亦同）可用const，constant或final（根据语言决定）等关键字标识，这时其值就会在编译时设定，并且无法在运行时改变。编译器通常将静态常量与文本一起置于目标文件的文本区域，而非常量初始化数据则置于数据区；而如若有需要，有些编译器还可选择为其开辟专用区；为防止常数变量被错误的指针写入覆盖，亦可在这块区域启用内存保护机制。

C族语言中的实现

在C语言及由其衍生出的C++与Objective-C等程序语言中，“static”是用于控制变量的生命周期和连接方式（即其作用域，亦即可见性）的保留字。确切来说，正如C族语言中的extern，auto与register这些保留字一样，static也是一种存储类（此处的“类”与面向对象语言的“类”的定义不同）标识。每个变量与函数都有以上的一种存储类标识，如果在声明中没有明确标识其存储类，编译时就会根据上下文来选择其默认存储类，如在源文件里的所有文件级变量对应的默认存储类是extern，而在函数体内的变量对应的则是auto，各存储类的属性如下表所列。

存储类名生命周期作用域extern静态（程序结束后释放）外部（整个程序）static静态（程序结束后释放）内部（仅翻译单元，一般指单个源文件）auto,register函数调用（调用结束后释放）无

易见存储类为extern的变量（包括上面提到的未明确声明存储类的文件级变量）符合前段所述静态变量的定义1，但不符合定义2。

不同情况下的作用

除明确标识出变量的外，将变量声明为static存储类还会根据变量属性不同而有一些特殊的作用：

 对于静态全局变量来说，针对某一源文件的以static声明的文件级变量与函数的作用域只限于文件内（只在文件内可见），也即“内部连接”,因而可以用来限定变量的作用域；

 对于静态局部变量来说，在函数内以static声明的变量虽然与自动局部变量的作用域相同（即作用域都只限于函数内），但存储空间是以静态分配而非默认的自动分配方式获取的，因而存储空间所在区域不同（一般来说，静态分配时存储空间于编译时在程序数据段分配，一次分配全程有效；而自动分配时存储空间则是于调用栈上分配，只在调用时分配与释放），且两次调用间变量值始终保持一致；必须注意，静态局部变量只能初始化一次，这是由编译器来保证实现。例如，gcc编译器对静态局部变量，首先获取guard变量，判断低字节是否为 0，若非零，表示已经初始化，可以直接使用。否则，将 guard 作为参数调用 __cxa_guard_acquire，如果锁成功，执行初始化静态变量的语句，然后释放锁。如果锁失败，说明产生竞态条件，则会阻塞当前线程。利用该机制，可以很好的实现所谓 Singleton 模式。对于单线程程序，静态变量初始化的互斥保护是没有必要的，gcc的-fno-threadsafe-statics 选项可以禁掉该机制。

 对于静态成员变量来说，在C++中，在类的定义中以static声明的成员变量属于类变量，也即在所有类实例中共享，与之相对的就是實例變數。

C示例
在C语言中，带有静态变量的程序如下所示：
#include <stdio.h>

void func() {
	static int x = 0; // 在对func的三次调用中,x只进行一次初始化
	printf("%d\n", x); // 输出x的值
	x = x + 1;
}

int main(int argc, char * const argv[]) {
	func(); // 输出0
	func(); // 输出1
	func(); // 输出2
	return 0;
}

C++示例

在C++中，带有含私有静态内部变量的类的程序如下所示：
class Request
{
	private:
		static int count; // 不能为外部调用
		string url; // 只能被成员函数调用

	public:
		Request() { count++; }
		string getUrl() const { return url; }
		void setUrl(string value) { url = value; }
		static int getCount() { return count; }
};
int Request::count = 0; // count 可以在类声明外进行初始化

 PHP示例 
<?php
function test(){
static $a = 0;//变量$a在第一调用test()时被初始化，每次调用 test() 函数都会输出 $a 的值并加 1
echo $a;
$a++;//，每次调用 test() 函数都会输出 $a 的值并加 1
}
?>

参见
 变量 (程序设计)

参考

 C程序设计语言（第二版），布莱恩·柯林汉与丹尼斯·里奇著 (Prentice Hall, 1984; ISBN 0-13-110362-8)
 C++程序设计语言（特别版），比雅尼·斯特劳斯特鲁普著(Addison Wesley, 2000; ISBN 0-201-70073-5)
 The GNU C Reference Manual , GNU.org
 Static Variables , University of Hawaii

Category:記憶體管理
Category:变量