C语言 全局、局部和静态局部变量

本文将探讨变量的作用域和生存期,并研究全局变量、局部变量和静态局部变量之间的区别。

一、局部变量和全局变量

1.局部和全局

从变量的 作用域 区分,变量可以分为:

局部变量:只能在对应区域内可以使用。

局部变量,定义在函数块内,代码块内的变量。会覆盖作用域更大的同名变量。

全局变量:在全局内可使用。

全局变量,定义在函数之外的变量。

注意:虽然在全局都可以用,但仍然需要先定义后使用。即作用范围是从定义的位置一直到文件末尾。

2.全局变量的使用

好处:

设置全局变量可以增加函数间数据联系的渠道。

坏处:

  • 安全性较低,破坏了函数的封装性,使代码可读性降低,难以维护和移植。
  • 全局变量会在全程占用存储单元

二、静态存储方式和动态存储方式

从变量的 生存期 区分,变量的存储可分为:

静态存储:在程序运行期间由系统分配固定的存储空间。在程序开始时分配空间,直到程序结束时才释放空间。会被赋初值。

动态存储:在程序运行期间由系统进行动态的空间分配。调用函数时,分配空间;函数结束时,释放空间。随机初值。

三、static关键字

若没有特殊声明,在函数内部定义的变量,在函数中定义时才分配空间,并伴随着函数的结束而被释放空间。

而通过 static 关键字定义静态变量,当函数结束后,变量不会被销毁。静态局部变量会继续存在,保持原值,并且无法被外界访问。

四、局部变量、全局变量和静态局部变量

仅讨论一般的局部变量和全局变量

类别 作用域 生存期 存储区
局部变量 代码块内 代码块内 动态存储区
全局变量 全局 全局 静态存储区
静态本地变量 代码块内 全局 静态存储区

五、局部变量的存储方式

1.自动变量:

动态存储,在程序开始时分配空间,程序结束时释放空间。

2.静态局部变量:

变量全局存在,且仅在局部内可以被访问。

3.寄存器变量:

将变量放置在寄存器上,用于加快对内存的存取效率,现在已经很少使用。

1
register int a;

六、扩展全局变量

一般而言,全局变量的作用域是从变量定义出开始,到本程序文件的末尾。但有时希望能够扩展全局变量,有以下几种情况:

1.扩展文件内的全局变量

若需要在全局变量定义位置之前使用全局变量,可以在使用位置之前用关键字 extern 对该变量作 “全局变量声明”,表示把该全局变量的作用域扩展到此位置。

1
2
3
4
void fun(){
printf("%d", a);
}
int a = 5;

此种方法必然报错,因为不能调用函数之后定义的全局变量。

1
2
3
4
5
extern int a;
void fun(){
printf("%d", a);
}
int a = 5;

这样便可以扩展全局变量的作用域。

  • 全局变量声明的类型名可以省略,例如:extern a;
  • 根据 《 C 程序设计》中的说法,在 C语言中, “全局变量声明”仅仅是声明,而其它对变量的声明都同时是定义。

2.扩展文件外的全局变量

在文件中定义的全局变量,作用域仅在文件中。如果一个程序包含两个文件,在两个文件中都要用到同一个全局变量 Num ,不能分别在两个文件中各自定义一个全局变量 Num ,否则在进行程序的连接时会出现“重复定义”的错误。正确的做法是:在任一文件中定义全局变量 Num ,而在另一文件中用 extern 对 Num 作”全局变量声明”。在编译和链接时,系统会因此知道 Num 有“外部链接”,可以从别的地方找到已定义的全局变量 Num,并将在另一文件中定义的全局变量 Num 的作用域扩展到本文件中,在本文件中可以合法地引用全局变量 Num 。

用此方法扩展全局变量的作用域应该慎重,因为在执行一个文件中的操作时,可能会改变该全局变量的值,从而影响另一个文件中全局变量的值。

给定 b 的值,输入 a 和 m,求 a*b 和 am 的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
file1:
#include <stdio.h>

int A;

int power(int);

int main(){
int b = 3;
int m;
int num1, num2;
printf("请输入a和m:\n");
scanf("%d %d", &A, &m);
num1 = A * b;
printf("%d * %d = %d\n", A, b, num1);
num2 = power(m);
printf("%d的%d次方=\n", A, m, num2);
}
--------------------------------------
file2:
extern A;
int power(int n){
int i, y = 1;
for (i = 1; i <= n; i++)
y *= A;
return y;
}

小问题:extern 既可以扩展文件内的全局变量,又可以扩展文件外的全局变量,系统如何区分呢?

在编译遇到 extern 时,先在本文件中找全局变量的定义,如果找到,则扩展文件内的全局变量;如果找不到,则在连接时从其他文件中找全局变量的定义,找到则扩展文件外的全局变量,还是找不到则按出错处理。

3.将全局变量限制在文件中

在程序设计中,如果希望全局变量只能被本文件引用,可以在定义时加一个 static 声明,这种变量被称为静态全局变量。

1
2
3
4
static int A;
int main(){

}

在程序设计中,常由若干人分别完成各个模块,通过这个方式可以使各人独立地在其设计的文件中使用外部变量而不与其它文件发生冲突。为程序的模块化、通用性、可移植性提供了方便。如果已经确定其它文件不需要引用本文件的外部变量,可以都加上 static ,将其对外“屏蔽”,以免被误用。

注意:不管加不加 static ,全局变量都会存储在静态存储区,这点与静态局部变量有区别。

七、总结

1.按作用域分

2.按生存期分

3.按存储方式分

参考