这是static关键字使用最多的情况。我们知道局部变量是在程序运行阶段在栈上创建的,但是static修饰的局部变量是在程序编译阶段在代码段(静态区)创建的。所以在static修饰的变量所在函数执行结束后该变量依然存在。
- //代码1
- #include
- void test()
- {
- int i = 0;
- i++;
- printf("%d ", i);
- }
- int main()
- {
- int i = 0;
- for(i=0; i<10; i++)
- {
- test();
- }
- return 0;
- }
- //代码2
- #include
- void test()
- {
- static int i = 0;
- i++;
- printf("%d ", i);
- }
- int main()
- {
- int i = 0;
- for(i=0; i<10; i++)
- {
- test();
- }
- return 0;
- }
我们可以比较一下上面两段代码的运行结果,很容易发现代码1中的i每次打印的值都相同,代码2中的i每次打印的值都是之前的值加上1,所以代码1中的i每次都会在test函数运行结束时被销毁,而代码2中的i不会被销毁。
需要注意的是:static int i=0这句代码作用于程序编译阶段,而程序运行阶段这句代码是不会产生任何效果的。为了验证这一点,我们可以进行如下操作:
- #include
- int main()
- {
- int j = 0;
- static int i = 0;
- return 0;
- }

这就是这段代码的汇编代码了,下面对这段汇编代码进行讲解
因为这条语句无汇编代码,所以程序运行过程中直接无视这条语句。该语句作用于程序编译阶段,编译阶段在运行阶段之前,也就是说静态局部变量i在程序编译阶段就创建好了,在整个程序运行结束之后才会被销毁。所以,static关键字延长了局部变量的生命周期。
同样的,经过static修饰的全局变量和局部变量一样,在程序编译阶段就会被分配内存
未经过static修饰的全局变量具有外部链接属性,使用extern关键字即可以跨文件使用
- //代码1
- //add.c
- int g_val = 2018;
- //test.c
- int main()
- {
- extern int g_val;
- printf("%d\n", g_val);
- return 0;
- }
-
-
- //代码2
- //add.c
- static int g_val = 2018;
- //test.c
- int main()
- {
- extern int g_val;
- printf("%d\n", g_val);
- return 0;
- }
运行这两段代码,我们发现代码1正常,代码2在编译的时候会出现连接性错误。;
所以,经static修饰的全局变量的生命周期不变,作用域变小,只能够在本源文件内使用
延申: 在使用extern声明外部变量时不能设定初始值,但是可以在声明之后单独给该变量赋值。
和static修饰全局变量十分类似,经过static修饰的函数的外部链接属性也被限制了,即只能在本源文件使用
- //代码1
- //add.c
- int Add(int x, int y)
- {
- return x+y;
- }
- //test.c
- int main()
- {
- printf("%d\n", Add(2, 3));
- return 0;
- }
-
-
- //代码2
- //add.c
- static int Add(int x, int y)
- {
- return x+y;
- }
- //test.c
- int main()
- {
- printf("%d\n", Add(2, 3));
- return 0;
- }
运行两段代码,我们发现代码1正常,代码2在编译的时候会出现连接性错误。
所以,一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。