C语言存储类别(Storage Class)
C语言中,存储类别(Storage Class)是一个标识符(也就是说函数和变量)的重要属性。存储类别决定着一个函数或变量的作用域(Scope,即可见性)和生命周期(Life time)。C语言中,主要有四种存储类别,即auto、register、static和extern,下面将一一说明。
1、auto
局部变量的缺省存储类别是auto,也就是说,下面两个变量的定义在存储类别层面对编译器来说是一样的。
{
int life;
auto int love;
}
存储类别为auto类型的标识符只能用在函数内部,比如做局部变量。其实,这是一种节省内存的方法,因为存储类别为auto的变量只在需要的时候才存在:当程序进入了它们所在的函数中时才会创建它们,而当退出这个函数时,它们也会随之被销毁。
2、register
register存储类别用来定义应该被存储在寄存器而非内存的变量。这样,一个存储类别为register的变量的最大不能超过寄存器的存储空间(通常是一个字长),并且register类型的变量不能用一元的&运算符来(也就是取地址操作符)操作。(很容易理解,因为register类型的变量是存储在寄存器,而非内存,所以不能用&来取它的内存地址。)。通常,register类型的变量通常用于经常被访问的变量,比如计数器。
{
register int counter;
}
当然,也要知道,register说明符只是建议编译器将该变量存储到寄存器中,但是,在实际中,编译器并不一定会这样做(比如,可能没有足够数量的寄存器供编译器使用)。实际上,现在性能优越的编译器能够识别出经常使用的变量,并将其放在寄存器中,而无需程序员给出register声明。
3、static
3.1 static对于全局变量
static是全局变量的缺省的存储类别,因此,下面的两个变量都有static的存储类别。
static int life;
int love;
int main()
{
printf("%d\n",life);
printf("%d\n",love);
}
3.2 在函数内部使用static
也可以在函数的内部对变量(这里自然是说局部变量)使用static,如果这样,那么该变量在编译的时候被初始化(并且仅会在编译的时候初始化一次,其他时候初始化语句不会起作用),并且能够在函数调用时,保留上次函数调用结束后该变量的值(实际上,向在上篇文章中提到的,这种变量是存储在程序内存区域的静态存储区,如果没有初始化,这里的变量都会被默认初始化为0)。注意,由于是在编译时初始化,因此,为static变量初始化的必须是一个常量,而不能是表达式或其他(在编译其程序还没开始运行,因此,没法计算表达式的值进行初始化)。下面的static变量可以用来保存函数的调用次数。
void func()
{
static count=1;
count++;
}
下面的例子,更加直接的说明了static变量的作用:
char *func();
int main()
{
char *t1;
t1=func();
}
char *func()
{
static char t2[10]="lfqy"
return t2;
}
上面的例子中,如果t2不声明为static,那么局部变量(存储类型为auto)在函数结束后会被释放掉,那么函数返回的地址将没有意义。如果将变量声明为static,那么该变量在程序运行期间都会存在,这样根据函数返回的地址,在整个程序中都可以访问到字符串“lfqy”。
3.3 在函数声明中使用static
如果将一个函数声明为static,那么该函数将只会在该文件中可见。
4、extern
简单地说,当extern用于变量时,extern声明了一个全局变量,该全局变量在其他程序文件中定义。通过该声明,在该文件中,可以引用该变量(该变量的定义在其它文件中)。因为该变量在其它文件中定义,而在该文件中只是进行声明,因此,不能在声明的时候进行初始化(该声明引用的是已经定义的全局变量所指向的内存空间,在定义时它已经被初始化,所以,在声明时不能被初始化)。
file1.c:
extern int count;
write()
{
printf("count is %d.\n",count);
}
file2.c
int count=5;
int main()
{
write();
return 0;
}
在上面的例子中,file1.c中能访问到count的值5,如果file1.c改变了count的值,那么在file2.c中也可以看到被改动的新值。