全局静态变量
在全局变量前加上static,就变成全局静态变量。
存放内存位置:静态存储区
存在期限:整个程序的运行期间一直存在
初始化:如果没有在初始化的时候赋值,就会被自动初始化为0
作用域:从定义的地方开始到文件的结尾,并且不能被其他文件使用。例如在a.c中定义了static int a=10;那么在b.c中用extern int a是拿不到a的值得,a的作用域只在a.c中。
static定义的静态局部变量分配在数据段上,普通的局部变量分配在栈上,会因为函数栈帧的释放而被释放掉。
局部静态变量
在局部变量前加上static,就是变成局部静态变量
存储位置:静态存储区
存在期限:局部(该函数的作用域)
初始化:未经初始化的全局静态变量会被自动初始化为0
作用域:作用域仍然为局部作用域,当它的定义语句结束的时候,作用域结速。但是局部静态变量离开作用域之后,并没有销毁,而是任然驻留在内存中,只是我们不能再对它进行访问,当再次调用该函数的时候,它的值任保留上次的值。
静态函数
在函数返回类型前
加static,函数就定义为静态函数。函数的定义和声明在默认情况下都是extern
的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
函数的实现使用static修饰,那么这个函数只可在本.c
内使用,不会同其他.c
中的同名函数引起冲突;
warning:不要在头文件中声明static的全局函数,不要在.c
内声明非static的全局函数,如果你要在多个.c
中复用该函数,就把它的声明提到头文件里去,否则.c
内部声明需加上static修饰;
实例
变量不加 static
//变量不加static,并且文件命名为 static_none.c
#include<stdio.h>
void test()
{
int num = 0;
num++;
printf("%d ",num);
}
int main()
{
int i;
for(i = 0; i<10; i++)
test();
printf("\n");
return 0 ;
}
运行结果
编译的环境是gcc编译器
$ gcc static_none.c -o static_none
$ ./static_none
输出
1 1 1 1 1 1 1 1 1 1
变量加static
//变量加上static,并把文件命名为static_add.c
#include<stdio.h>
void test()
{
static int num = 0; //添加static
num++;
printf("%d ",num);
}
int main()
{
int i;
for(i = 0; i<10; i++)
test();
printf("\n");
return 0 ;
}
$ gcc static_none.c -o static_none
$ ./static_none
输出
1 2 3 4 5 6 7 8 9 10
总结:
不加static修饰,函数或者代码块中的变量在函数或者代码块执行完毕后就直接回收销毁了,每次执行都会重新分配内存,每次都会销毁。
加 static 修饰,函数或者代码块中的变量在函数或者代码块执行第一次初始化分配内存后,就算函数或者代码块执行完毕,该变量也不会被回收 销毁,直到程序结束 static 变量才会被回收。
当 static 作用于函数定义时,或者用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性。外部链接属性变为内部链接属性,标识符的存储类型和作用域不受影响。也就是说变量或者函数只能在当前源文件中访问,不能在其他源文件中访问。
当static 作用于代码块内部的变量声明时,static关键字用于修改变量的存储类型。从自动变量变为静态变量,变量的属性和作用域不受影响。
特点: static局部变量的”记忆性”
与生存期的”全局性”
所谓”记忆性”是指在两次函数调用时, 在第二次调用进入时, 能保持第一次调用退出时的值.
注意事项:
-
“记忆性”, 程序运行很重要的一点就是可重复性, 而static变量的”记忆性”破坏了这种可重复性, 造成不同时刻至运行的结果可能不同.
-
“生存期”全局性和唯一性. 普通的local变量的存储空间分配在stack上, 因此每次调用函数时, 分配的空间都可能不一样, 而static具有全局唯一性的特点, 每次调用时, 都指向同一块内存, 这就造成一个很重要的问题 —- 不可重入性