static 在中文里的意思是静止的,然而,它却并不安分。在C语言中,我们可以使用它来声明静态变量。
在内存中,其存储区域主要分为三大块:
- 栈,用来存储局部变量,其生命周期维持在所在函数的生命周期内。当函数运行结束,其存储的内容会自动销毁。
- 堆,用于存储
malloc
或new
动态分配的内存空间,其生命周期由free
或delete
决定。 - 静态区,存储自动全局变量与
static
关键字声明的变量。其生命周期在程序运行过程持续存在。
讲了这么多,关键是最后一句其生命周期在程序运行过程持续存在。
可以先看一下下面这个程序:
#include "stdio.h"
int fun(void)
{
static int n = 0;
n++;
return n;
}
int main(void)
{
int i = 0;
for(i = 0; i < 10; i++)
{
fun();
}
printf("%d", fun());
return 0;
}
程序最终的输出结果是什么呢? 0 还是什么?
在函数fun
中,n
虽然作用域仅限制于fun
函数中,但是因为被static
声明为静态变量,因此其生命周期会持续存在,因此在函数执行完了以后,n并没有被销毁。第二次调用fun函数时,n
已经不是等于 0 了。
此外,如果在声明时静态变量时不赋初值(把n = 0
的=0
去掉)可以吗?我试了多种编译器,证明声明静态变量是会被默认赋值 0 的。不过这样写代码可读性不好,容易造成误解。所以,一般还是给它赋个初值吧~
关于上面那个程式,如果在n++
前加上n = 0
,结果又会等于什么呢?可以先思考一下,然后运行看看对不对~
static
出了在函数内部声明局部的静态变量外,也可以用于在函数外声明全局的静态变量。但是,从表面上看,似乎看不出有有什么作用(已经是全局变量,加不加都是生命周期在程序运行过程持续存在)。
但是如果你进行多个文件编译,就可以看出区别了。
A文件(a.c):
int j = 1;
int fun(void)
{
return j;
}
B文件(b.c):
#include "stdio.h"
int j;
extern int fun();
int main(void)
{
j = 2;
printf("%d", fun());
return 0;
}
如果在VC中将这两个文件放在同一个空间内编译(或在 gcc 中一起编译)。编译器将会报出一个错误:“int j” 已经在 a.obj 中定义。因为你将两个相同的变量在同样的作用域里声明了两次。
那么,这时,你在其中一个int j;
前加上static
,然后再编译,咦?错误没了。运行,结果等于1。也就是,a 文件里的 j 已经不是 b 文件里的j 了~
在这里,static
还具备另一个作用——限定作用域。它把被声明的变量的作用域限定在了本文件中了。因此,a 文件的 j 也就不会与之冲突了。
static 也可以被用来声明函数,有时为了开发一个项目,会多人多文件的协作开发,但是有些函数只是内部调用,为了避免与别人定义的函数冲突,可以在前面加上 static ,把函数的作用域限定在本文件中。
细心的同学可能会发现,在B文件中,有这么一句:
extern int fun();
extern 又是用来做什么的?这个,下次再说~今天就先这样~
PS:在 C++ 中,又对 static 的功能做了扩充(可怜的 static ……T_T),有机会再我再去整理一下~