春暖花开

C 语言中的静态变量

静态变量

静态变量的关键字为 static ,采用静态存储方式,一般的声明如:

1
static int a;//a 为一个静态变量

静态变量的一些特点:

  • 静态局部变量在函数内定义,但不像自动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。
  • 静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
  • 允许对构造类静态局部量赋初值。若未赋以初值,则由系统自动赋值。数值型变量自动赋初值0,字符型变量赋空字符。
  • 对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。 根据静态局部变量的特点, 可以看出它是一种生存期为整个源文件的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。

尽管如此,全局静态变量和局部静态变量还有一些区别。

全局静态变量

尽管全局静态变量的生命周期为整个源程序,但是,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。

局部静态变量

在一些函数比如递归函数中,局部静态变量用处较大,比如在递归函数中。但是需要注意,每次在主函数中调用该函数时,局部静态变量都保存之前的值。此时,需要注意一个问题。

如果在一个递归函数中,当递归调用时,需要静态变量保存之前的值,而每次在主函数中调用该递归函数,都需要将该静态变量赋一个固定的初值,那么可以多加一个参数来实现。

下面是一个例子。通过中序遍历一个平衡二叉排序树来获取一个递增序列,将该序列存于一个数组中,并得到数组的最后一个元素下标。

第一种实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int inorder(BiTree T, int key[], int *last){
static int i = 0;
if(!T)
return 1;
else{
if (inorder(T->lchild, key, last, ++ restore)){
key[i++] = T->data;//get array list
if (inorder(T->rchild, key, last, ++ restore)){
*last = i - 1;// get the length-1 of list
return 1;
}
}
return 0;
}
}//inorder

如果在主函数中,该函数仅调用一次,那么像这样写没有任何问题。但是,如果主函数中多次调用了该递归函数,那么之后的调用 i 的初值遍不是 0 ,而这儿我们需要在是 0 ,当每次在主函数中调用时。

我们可以通过添加一个参数来保证每次在主函数中调用该递归函数时,i 的初值均为 0:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int inorder(BiTree T, int key[], int *last, int restore){
static int i = 0;
if (!restore)
i = 0;//when everytime call the function in main function, restore i to zero
if(!T)
return 1;
else{
if (inorder(T->lchild, key, last, ++ restore)){
key[i++] = T->data;//get array list
if (inorder(T->rchild, key, last, ++ restore)){
*last = i - 1;// get the length-1 of list
return 1;
}
}
return 0;
}
}//inorder

如上面的代码所示,我们增加了一个新的参数 restore,每次在主函数中调用该函数时,restore 传入的值为 0 ,这样便可消除上面的问题。

0%