静态局部变量、静态全局变量、extern全局变量、自动变量 札记

时间:2023-03-08 16:42:27
  1. 静态局部变量

  静态局部变量。

  从称呼上我们可以看出,静态局部变量首先是一个局部变量,因此其只在定义它的函数内有效,冠以静态的头衔后,其生存期就被延长了,不会随着函数的返回而被撤销。我们可以这样来理解:静态局部变量就是在程序生存期间一直有效,但只能在定义它的函数中使用的一种变量。

  静态局部变量的声明比较简单,在声明局部变量的时候,加上关键字static就可以了。下面是一个用局部静态变量计算阶乘的具体例子。

#include “stdio.h”

int fac(int n)
{
static int nRet = 1; //静态局部变量 nRet *= n; return nRet;
} void main()
{
for(int i=1;i<5;i++)
{
printf(“%d!=%d\n“,i,fac(i));
}
getchar();
}

在第一次调用函数fac的时候,函数fac中的静态局部变量nRet被初始化为1,如果没有默认指定初始化值得话,会被默认初始化为0. 主函数main*进行了4次fac函数的调用:

  第一次调用:初始化nRet为1 函数返回时:nRet=1

  第二次调用时: nRet=1  函数返回时:nRet=2

  第三次调用时: nRet=2  函数返回时:nRet=6

  第四次调用时: nRet=6  函数返回时:nRet=24

  可以看出,静态局部变量在第一次调用的时候进行初始化,每次函数调用后,静态局部变量不会像局部变量那样被立即释放,而是继续有效,在下一次函数调用的时候会继续使用上一次的值。

静态局部变量总结:

    (1)静态局部变量可以不初始化,有系统设置默认值为0;

    (2)静态局部变量默认只会在最开始定义静态局部变量时初始化,并且只有这唯一的一次初始化;

    (3)静态局部变量的作用范围仅仅只是块(如函数)内部。

  2.静态局部变量与其他变量类型的关系

  

    全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。

  静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。

  局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。

  静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。

  从分配内存空间看: 全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。

使用的tips:

  Tips:
  A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
  B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
  C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题,因为他们都放在静态数据存储区,全局可见;
      D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)
      E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。

  3. static VS auto, static 全局变量 VS extern 全局变量

和局部static相反的保留字是auto(一般可以不写,我们通常声明的变量,如 int a =19, 等,就是auto变量),static变量的生存期是永久(对于我们可见的代码来说),只初始化一次;而auto变量的生存期与所在块(复合语句)相同,每次进入块时进行初始化,
如果是对象类型则在声明的地方执行构造语句。

  全局static变量是这样的:
  static int a;
  main()
  {
  ...
  }
  这时和它相反的是extern,这时static表明这个全局变量是“文件级”的,只能在这个文件中可见,但生存期和其它全局变量相同。

4.从作用域的角度考虑

extern全局变量、static全局变量和static局部变量的生存期都是“永久”(即:程序存在期间一直都可以使用),区别只是可见域不同。extern全局变量可见区域是工程,static全局变量可见区域是文件,而static局部变量的可见区域是块。
从代码维护角度来看,对extern变量的修改可能会影响所有代码,对static全局变量的修改可能影响一个文件中的代码,而对static变量的修改可能影响一个块的代码;因此在选择变量类型时,优先级是static局部>static全局>extern全局。但它们有着共同的缺点:使用了这些类型变量的函数将是不可重入的,不是线程安全的。在C/C++标准库中有很多函数都使用了static局部变量,目前的实现中都为它们提供了两套代码,单线程版本使用static变量而多线程版本使用“线程全局变量”,比如rand,strtok等。

5.自动变量示例

自动变量:局部没有经过任何修饰的局部变量叫自动变量 (它存在于动态数据区——栈),这个区域内的数据随着程序的运行动态的生成和释放,函数返回就释放,函数要调用就生成。关键字:默认是atuo(一般不写).

 自动变量的特点:当程序执行到自动变量的作用域的时候就分配,不是到了声明代码才分配哦!到了代码分配就晚啦!当定义自动变量的函数执行结束后,程序将释放该自动变量的存储空间,留给其他自动变量使用。

#include <stdio.h>

void add(int n)
{
auto int s = 0;
s = s + 1; printf("No.%d: s=%d\n", n, s);
} void main()
{
int i = 1; for(i; i<4; i++)
{
add(i);
}
}

输出为:

No.1: s=1

No.2: s=1

No.3: s=1

从这个例子不难看出,自动变量的初始值在每次分配存储空间后都要重新赋值。