C中变量的存储类型、生存期和作用域
C中,按变量的存储类型可将变量分为:自动变量(auto)、寄存器变量(register)、外部变量(extern)和静态变量(static)。
1、自动变量(auto)
定 义:在各个函数或复合语句内定义的变量,也称局部变量。用关键字auto标识,可缺省(即在定义时若省略了存储类型,系统将默认其为自动型变量)。当希望某个变量只在函数内使用,可将其定义成自动型,以充分利用内存。
作用域:在定义该变量的函数或复合语句内。
存 储:分配在内存的堆栈段,采用动态存储的方式,即在函数运行时在堆栈中分配存储空间,一旦函数调用结束,就释放该变量。
例 如:
#include
void main()
{ int x=1,y=2;
{ int x=10;x=x+10;
printf("x=%d,",x);
printf("y=%d,",y);
}
x=x+9;
printf("x=%d\n",x);
}
结果:x=20,y=2,x=10
2、寄存器变量(register)
定 义:如果一些变量使用频繁,可定义为寄存器变量。由于对寄存器的存取速度远远高于对内存的读取速度,因而这样可以提高执行效率。
存 储:分配在CPU的通用寄存器中。
例 如:for循环中所用到的变量。
说 明:
(1)、由于CPU通用寄存器数量有限,程序中允许定义的寄存器变量一般以两个为宜。若定义的寄存器变量的数目多于所提供的寄存器数目,超出的变量将由编译系统自动设为自动型。
(2)、对于占用字节数多的变量(long、float、double等)及数组不宜定义为寄存器型变量。
(3)、当今的优化编译系统能够识别使用频繁的变量,从而自动地将这些变量放在寄存器中,因而一般不需要再由程序员指定。
3、外部变量(extern)
定 义:在所有函数(包括主函数)外部定义的变量,也称为全局变量。
存 储:分配在内存的静态数据存储区。
作用域:从外部变量定义点开始,直到源程序运行结束,即其作用具有全局性。
引用方式:当外部变量在定义点之前或别的源程序中要引用外部变量,则在引用该变量之前,需进行外部变量的引用说明。
例 如:
#include
int x=10;
void f()
{ extern int y; //外部变量的引用说明
x++;
printf("x=%d,",x);
printf("y=%d\n",y);
}
int y=2;
void main()
{ int x=1;
x++;
f();
printf("x=%d,y=%d\n",x,y);
}
结果:
x=11,y=2
x=2,y=2
分析:
若f()中没有“extern int y;”语句,则会出错;或将语句“int y=2;”放在第二句“int x=10;”之后,则不需要外部变量y的引用说明语句。
从结果可知,当外部变量和自动变量在同一个模块中有
效时,自动变量起作用。
4、静态变量(static)
(1)、静态局部变量
定 义:在函数体的复合语句中定义,用“static”进行标识。
存 储:分配在内存的静态数据存储区。
生存期与作用域:全局寿命、局部可见。即只有在编译时可以赋初值,以后每次调用时不再分配内存单元和初始化,只是保留上一次函数调用结束时的值。直到程序运行结束,对应的内存单元才释放。而其作用域仅仅只限于所定义的函数或复合语句。
例 如:
#include
void f1()
{ int x=1;
x++;
printf("x=%d,",x);
}
void f2()
{ static int x=1; //静态局部变量的定义
x++;
printf("x=%d\n",x);
}
void main()
{ f1();f2();
f1();f2();
}
结果:
x=2,x=2
x=2,x=3
分析:
由于f2函数中定义的x变量是一个静态的局部变量,当f2函数第二次调用时,x变量不再分配内存单元,不再进行初始化,其值是第一次调用结束的值2,因此第二次调用f2函数输出x变量的值为3。
而f1函数定义的变量x是局部变量,每次调用都要分配内存单元和初始化为1,每次调用结束内存单元都要释放,所以每次输出值都相同。
(2)、静态全局变量
定 义:在所有函数(包括主函数)之外定义的,用“static”标识的变量。
存 储:分配在内存的静态数据存储区。
生存期和作用域:全局寿命、局部可见。即在整个程序运行期间都存在;但它与外部变量(即全局变量)不同,静态全局变量只能在所定义的文件中使用,具有局部可见性(注意它与静态局部变量的“局部可见”是不一样的),而外部变量可在其他文件中使用。
说 明:自动变量没有赋初值,其值是一个随机值;静态变量和外部变量没有赋初值,其值为0。
例 如:静态全局变量与外部变量的区别(笔者是在VC 6.0下进行测试)
第一个文件的内容如下:
/*file1.c*/
#include
int a=2;
static int b=3; //此处的变量b只能在file1.c中使用
void func()
{ a++;b++;
printf("a=%d,b=%d\n",a,b);
}
第二个文件的内容如下:
/*file2.c*/
#include
extern int a;
int b; //初始化b为0
void main()
{ func();
printf("a=%d,b=%d\n",a,b);
}
将file1.c及file2.c放在同一个文件夹中。
再新建工程文件:在VC6.0中新建Win32 Console Application工程文件,取名为file(建立后的工程文件后缀是.dsp),注意所建工程文件位置应和file1.c及file2.c在同一个文件夹中。建立后打开工程文件,切换到FileView,右击Source File
s,添加file1.c及file2.c进去,运行查看结果。
结果:a=3,b=4
a=3,b=0
分析:文件file1.c中的全局变量a可以在文件file2.c中使用,只需要加上声明语句“extern int a;”即可。但file1.c中的静态全局变量b不能在file2.c中使用。如果将file.c文件中的变量定义语句“int b;”改为“extern int b;”,则会出现“file2.obj : error LNK2001: unresolved external symbol _b”错误。