静态变量static
静态变量可以分为:静态全局变量、静态局部变量。
静态变量作用的范围是在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0。
静态变量或者静态函数只在本文件内的代码才能访问,它的名字在其他文件中不可见。
代码一:static
从代码可以看出:用static在不同文件中,定义同名函数和同名变量,不会产生命名冲突。
1 #include "stdafx.h" 2 #include "iostream" 3 using namespace std; 4 5 void fn(); 6 //static int n; //另一个文件中有n,依然可以运行 7 int n; ////另一个文件中有n,会报错 8 9 10 int _tmain(int argc, _TCHAR* argv[]) 11 { 12 n = 20; 13 cout << n << endl; 14 fn(); 15 system("pause"); 16 return 0; 17 } 18 19 void fn() 20 { 21 n++; 22 cout << n << endl; 23 }
代码二:
从代码可以看出:两次调用之间可以对变量进行保存。
首先来看程序在内存中的分配:
在函数体内定义一个变量,每当程序运行到该语句时,都会给该局部变量分配栈内存。随着函数退出函数体,系统就会收回栈内存,局部变量也相应失效。但是有时候需要在两次调用之间对变量的值进行保存。通常想法是定义一个全局变量来实现,但是定义全局变量,变量就不在属于函数本身,不在受函数的控制,给程序维护带来不便。静态局部变量正好解决这个问题,静态局部变量保存在全局数据区,而不是在栈中,每次的值保存到下次运算。
1 #include "stdafx.h" 2 #include "iostream" 3 using namespace std; 4 5 void fn(); 6 7 int _tmain(int argc, _TCHAR* argv[]) 8 { 9 fn(); 10 fn(); 11 fn(); 12 system("pause"); 13 return 0; 14 } 15 16 void fn() 17 { 18 static int n = 10; //static int结果是10,11,12 19 cout << n << endl; //int 结果为10,10,10 20 n++; 21 }
由上程序可以看出static每次保存运算中间值。
如果在全局变量前加static,就会对源文件隐藏。利用这一特性可以在不同的文件中定义同名函数和同名变量,不必担心命名冲突。statci可以用作函数和变量的前缀,对于函数而言,static作用仅用于隐藏。对于变量而言,static作用还有上述的存储变量的值。static变量的初始化为0。
全局变量、静态全局变量、静态局部变量、局部变量的区别:
1.存储区域:全局变量、静态全局变量、静态局部变量都存放在全局/静态存储区,局部变量存储在栈区。
2.全局变量具有全局可见性,其他源文件也可以访问,在整个工程文件内都有效。静态全局变量只在定义它的文件内有效,其他源文件不可见(故不会发生命名冲突),静态全局变量只初始化一次。静态局部变量只在定义它的函数内有效,程序只分配内存一次,函数返回后,该变量不会消失。局部变量仅在定义的函数内有效,函数返回后失效。
static全局变量和普通全局变量的区别:static全局变量只初始化一次,防止其他文件单元中被引用。
static局部变量和普通局部变量的区别:static局部变量只被初始化一次,下次计算依据上次结果值。
static全局变量、静态变量没有手工初始化。则编译器初始化为0。局部变量值则不知。
static函数和普通函数区别:static函数在内存中只有一份,普通函数在每个调用中维持一份拷贝(每个调用只有一个复制,内联函数是每次调用都将代码展开)。
若全局变量仅在单个c文件中访问,可以将这个变量修改为静态全局变量,降低模块间的耦合度。
若全局变量仅由单个函数访问,则可以将这个变量改为函数的静态局部变量,以降低模块间的耦合度。
设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,要考虑重入问题。
ps:可重入函数:能够被多个线程“同时”调用的函数,并且保证函数结果正确性的函数。在C语言中编写可重入函数,尽量不要使用全局变量或者静态变量。如果使用了,要注意这类变量访问的互斥。
一般采用以下几种保证函数的可重入性:信号量机制,关调度机制,关中断机制等。一般驱动是不可重入函数。