C语言中对变量的说明包括两方面的内容:变量类型以及变量的存储类型。变量类型如:int(整形),char(字符型)是用来说明变量所占用的内存空间的大小。变量存储类型用来说明变量的作用范围。
C语言的变量存储类型有:自动类、寄存器类、静态类和外部类。
局部变量是指在函数内部说明的变量(有时也称为自动变量),用关键字auto进行说明。 所有的非全程变量都被认为是局部变量,所以auto实际上从来不用。局部变量在函数调用时自动产生,但不会自动初始化, 随函数调用的结束,这个变量也就自动消失了,下次调用此函数时再自动产生,还要重新赋值,退出时又自动消失。
静态变量用关键字static声明。根据变量的类型可以分为静态局部变量和静态全程变量。
它与局部变量的区别在于:在函数退出时,这个变量始终存在,但不能被其它函数使用,当再次进入该函数时,将保存上次的结果。其它与局部变量一样。
静态全程变量就是指只在定义它的源文件中可见而在其它源文件中不可见的变量。它与全程变量的区别是:全程变量可以再说明为外部变量(extern),被其它源文件使用,而静态全程变量却不能再被说明为外部的,即只能被所在的源文件使用。
下面结合具体代码来分析一下变量的种类。
在file1.c的开头声明i是全程变量,并初始化为1。而在main函数内部,说明了两个自动变量i和j,这样在main内部出现的i就是自动变量。
file1.c
#include <stdlib.h>
#include <stdio.h>
int reset();
int next();
int last();
int sum(int );
int i=1;
void main()
{
auto int i,j;
i=reset();
for(j=1;j<=3;j++)
{
printf("i=%dtj=%dn",i,j);
printf("next(i)=%dn",next());
printf("last(i)=%dn",last());
printf("sum(i+j)=%dn",sum(i+j));
}
}
file2.c文件一开始就定义了变量i,并声明为静态变量,因此它的使用范围只在当前文件中使用。然而从函数sum中定义来看,其内部用到的i是形式参数,j是内部静态变量,它们与以前的i, j都不同。
file2.c文件
static int i=10;
int next()
{
return(i+=1);
}
int last()
{
return(i-=1);
}
int sum(int i)
{
static int j=5;
return(i=j+=i);
}
在file3.c的开头说明i是外部的,表明它与file1.c定义的i是同一个变量,所以reset的值返回的就是这个i的当前值1。
file3.c文件
extern int i;
reset()
{
return(i);
}
具体执行过程分析如下:
附:运行结果
i=1 j=1 next(i)=11 last(i)=10 sum(i+j)=7 i=1 j=2 next(i)=11 last(i)=10 sum(i+j)=10 i=1 j=3 next(i)=11 last(i)=10 sum(i+j)=14
解析static关键字
static在c里面可以用来修饰变量,也可以用来修饰函数。
先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不包含对,不要弄混。
int a;
main()
{
int b ;
int c* = (int *)malloc(sizeof(int));
}
a是全局变量,b是栈变量,c是堆变量。
static对全局变量的修饰,可以认为是限制了只能是本文件引用此变量。有的程序是由好多.c文件构成。彼此可以互相引用变量,但加入static修饰之后,只能被本文件中函数引用此变量。
static对栈变量的修饰,可以认为栈变量的生命周期延长到程序执行结束时。一般来说,栈变量的生命周期由OS管理,在退栈的过程中,栈变量的生命也就 结束了。但加入static修饰之后,变量已经不在存储在栈中,而是和全局变量一起存储。同时,离开定义它的函数后不能使用,但如再次调用定义它的函数 时,它又可继续使用, 而且保存了前次被调用后留下的值。
static对函数的修饰与对全局变量的修饰相似,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。