分类: C/C++
2009-05-29 14:35:22
一、首看static
static 类型声明符在C语言里面主要有三个用途:
1、声明静态局部变量。
2、声明静态外部全局变量。
3、声明静态外部函数。
三个用法的解释说明:
静态局部变量(与auto对比)
1、 存储空间分配、作用域和生存期
static分配在静态存储区,作用域仅仅限于声明该变量的函数内部。在程序
整个运行期间都不释放,生存期贯穿于程序运行的整个过程。
auto类型分配在栈上,属于动态存储类别,占动态存储区空间,作用域仅仅限于声明该变量的函数内部。函数调用结束后自动释放,生存期不过是在声明该变量的函数内部。
2、赋初值时的处理方式
static静态局部变量在编译时赋初值,即只赋初值一次;
auto自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
3、未赋初值时的处理方式
如果在定义局部变量时不赋初值的话:
static静态局部变量,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。
auto自动变量,如果不赋初值则它的值是一个不确定的值。
例如:
int fun(void);
int main(void)
{
int x;
x=fun();
printf(" First transfer function a is %d\n",x);
x=fun();
printf(" Second transfer function a is %d\n",x);
x=fun();
printf(" Third transfer function a is %d\n",x);
getch();
return 0;
}
int fun(void)
{
int a=0;
a+=100;
return a;
}
程序结果为:
First transfer function a is 100
Second transfer function a is 100
Third transfer function a is 100
那么我们稍稍做下修改,将fun中的a定义成static int
fun函数如下:
int fun(void)
{
static int a=0;
a+=100;
return a;
}
程序执行结果:
First transfer function a is 100
Second transfer function a is 200
Third transfer function a is 300
对比两个函数我们可以发现,普通局部变量是进入函数是产生,退出函数时候消亡,static局部变量使子程序多次调用之间保持局部变量值。也就是说当第一次调用后,a的值是100,第二次调用a的初始值不是0而是100。
静态外部全局变量
在C语言中static还用来声明静态外部全局变量,那么这个全局变量的作用域就被限制在本文件内部。
外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。
而如果我们声明的全局变量不想被其他文件访问和使用又该怎么办?
那就是在声明的时候前面加上关键字static。
例如:
static int a;
int fun(void);
void fun2(int y);
int main(void)
{
int x;
fun2(100);
x=fun();
printf(" First transfer function a is %d\n",x);
x=fun();
printf(" Second transfer function a is %d\n",x);
x=fun();
printf(" Third transfer function a is %d\n",x);
getch();
return 0;
}
int fun(void)
{
a+=100;
return a;
}
void fun2(int y)
{
a=y;
}
程序结果为:
First transfer function a is 200
Second transfer function a is 300
Third transfer function a is 400
其效果和static局部变量一样,只不过是在整个文件中可见。
fun可以访问,fun2可以访问。而在第一个例子中只能是在fun中可见。
静态外部函数
在C语言中我们的函数默认都是全局的,也就是说你可以调用其他文件中的函数。在使用的时候,我们象前面一样在头文件中加上extern就可以了。但是有时候我们写的函数并不想让别的文件访问和调用,那么我们在声明函数的时候前面加上static就可以了。
使用内部函数的好处有二:
1、可以让某些内部函数不为人所能使用,而仅仅让调用者使用他能使用的东西,有利于保护代码。
2、不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
例如:
//teststatic1.c
void display();
static void staticdis();
int main()
{
display();
staticdis();
renturn 0;
}
//teststatic2.c
void display()
{
staticdis();
printf("display() has been called \n");
}
static void staticdis()
{
printf("staticdis() has been called\n");
}
文件分别编译通过,但是连接的时候找不到函数staticdis()的定义,产生错误。
二、再看static
5)堆——动态存储分。
二、 C语言的static
2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
2、问题:Static的理解 关于static变量,请选择下面所有说法正确的内容: A、若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度; B、若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度; C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题; D、静态全局变量过大,可那会导致堆栈溢出。
答案与分析: 对于A,B:根据本篇概述部分的说明b),我们知道,A,B都是正确的。
对于C:根据本篇概述部分的说明a),我们知道,C是正确的(所谓的函数重入问题,下面会详细阐述)。
对于D:静态变量放在程序的全局数据区,而不是在堆栈中分配,所以不可能导致堆栈溢出,D是错误的。
因此,答案是A、B、C。
3、问题:不可重入函数 曾经设计过如下一个函数,在代码检视的时候被提醒有bug,因为这个函数是不可重入的,为什么?
unsigned int sum_int( unsigned int base )
{ unsigned int index;
static unsigned int sum = 0; // 注意,是static类型的。
for (index = 1; index <= base; index++)
{ sum += index; }
return sum; }
答案与分析: 所谓的函数是可重入的(也可以说是可预测的),即:只要输入数据相同就应产生相同的输出。
这个函数之所以是不可预测的,就是因为函数中使用了static变量,因为static变量的特征,这样的函数被称为:带“内部存储器”功能的的函数。因此如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量,这种函数中的static变量,使用原则是,能不用尽量不用。
将上面的函数修改为可重入的函数很简单,只要将声明sum变量中的static关键字去掉,变量sum即变为一个auto 类型的变量,函数即变为一个可重入的函数。
当然,有些时候,在函数中是必须要使用static变量的,比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。 出处: 日期:2005-04-14 var reload=1;