一、static定义局部静态变量(staic放在函数体内部)
1.1 存储空间分配不同
与auto变量不同的是,static变量的内存分配在静态数据区(data segment),而不是在栈内分配。如果两者在相同的地方定义,那么auto变量与static的作用域相同,但是他们的生存期不同。如果都定义在函数内,那么在函数销毁时auto变量就销毁,但是static变量会一直持续到程序运行结束(全局性)。如果在一个函数内定义一个auto变量,在函数结束时是不能返回该变量的,但是如果在函数局部定义一个static变量,那么在函数结束时是可以返回该变量的,因为该变量在整个程序运行期间都存在.
int func (){
int a = 10;
return a; //错误,在函数func结束时变量a已经被销毁,不能返回
}
int func2( ){
static int a=10;
return a; //正确,由于a是静态变量,整个程序运行都存在,并不会随着函数的调用结束而销毁,因此可以返回他的值
}
1.2 初始化不同
static变量只进行一次初始化, 如果static变量定义时没有赋值,那么默认值是0。(由于static变量存储在静态数据区,该区域的内存都默认初始化为0,所以可以利用这个特性来对数据进行初始化)
如果一个static变量定义并初始化在一个函数内,在第一次调用函数时该变量会进行定义并初始化,在以后的函数调用过程中,定义和初始化的过程将不在执行:
int func ( ){
static int a =10;
printf("%d\n",a--); //静态变量a只被初始化一次,每次函数调用a的值是上一次函数调用结束时的值
}
int main()
{
for(int i=0; i<10; i++){
func( );
}
}
最终函数的输出是 10, 9, 8,7,6,5,4,3,2,1。 变量a只被初始化一次,而不是每次调用函数都重新定义一个变量a再进行初始化,当下次调用函数时变量a保持上一次函数调用结束时的值(static变量的记忆性)。
二、外部静态变量、函数(static放在函数体内部)
在C中static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。, 但为了限制全局变量/函数的作用域, 函数或变量前加static使得函数成为静态函数。此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。注意此时, 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区, 生存期都是全局的。 此时的static只是起作用域限制作用, 限定作用域在本模块(文件)内部.
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
//file1.c
int a;
static int b;
int func1( ){ ...}
static int func2( ) {...}
//file2.c
extern int a; //正确,使用file1.c中的全局变量
extern int b; //错误,不能使用file.c中的全局静态变量
func1( );
func2( );
三、静态数据成员/成员函数(C++特有)
C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数. 这是与普通成员函数的最大区别, 也是其应用所在, 比如在对某一个类的对象进行计数时, 计数生成多少个类的实例, 就可以用到静态数据成员. 在这里面, static既不是限定作用域的, 也不是扩展生存期的作用, 而是指示变量/函数在此类中的唯一性. 这也是”属于一个类而不是属于此类的任何特定对象的变量和函数”的含义. 因为它是对整个类来说是唯一的, 因此不可能属于某一个实例对象的. (针对静态数据成员而言, 成员函数不管是否是static, 在内存中只有一个副本, 普通成员函数调用时, 需要传入this指针, static成员函数调用时, 没有this指针. )
请看示例程序四((影印版)第59页)
class EnemyTarget {
public:
EnemyTarget() { ++numTargets; }
EnemyTarget(const EnemyTarget&) { ++numTargets; }
~EnemyTarget() { --numTargets; }
static size_t numberOfTargets() { return numTargets; }
bool destroy(); // returns success of attempt to destroy EnemyTarget object
private:
static size_t numTargets; // object counter
};
// class statics must be defined outside the class;
// initialization is to 0 by default
size_t EnemyTarget::numTargets;
在这个例子中, 静态数据成员numTargets就是用来计数产生的对象个数的.
另外, 在设计类的多线程操作时, 由于POSIX库下的线程函数pthread_create()要求是全局的, 普通成员函数无法直接做为线程函数, 可以考虑用Static成员函数做线程函数.
阅读(1405) | 评论(0) | 转发(0) |