在 C 语言中,存储模型,也即存储类,使用存储时期(storage duration)或者作用域(scope)以及它的链接(linkage)来定义了 5 种存储类:自动、寄存器、具有代码块作用域的静态、具有外部链接的静态和具有内部链接的静态。下表列出了这些组合的简要说明:
| 存储类 |
时期 |
作用域 |
链接 |
声明方式 |
| 自动 |
自动 |
代码块 |
空 |
代码块内 |
| 寄存器 |
自动 |
代码块 |
空 |
代码块内,使用关键字 register |
| 具有外部链接的静态 |
静态 |
文件 |
外部 |
所有函数之外 |
| 具有内部链接的静态 |
静态 |
文件 |
内部 |
所有函数之外,使用关键字 static |
| 空链接静态 |
静态 |
代码块 |
空 |
代码块内,使用关键字 static |
术语解释
- 作用域
用于描述程序中可以访问的区域。一般分为代码块作用域(block scope)、函数原型作用域(function prototype scope)和文件作用域(file scope)。其中文件作用域也被称为全局变量(global variable),其它称为局部变量(local variable)。另外还有一种比较少用的函数作用域(function scope),但它只适用于 goto 语句使用的标签。
- 链接
包括外部链接(external linkage),内部链接(internal linkage)和空链接(no linkage)。具有文件作用域的变量可能有内部或外部链接,具有外部链接的变量可以在一个多文件程序的任何地方使用,一个具有内部链接的变量可以在一个文件的任何地方使用。其中变量的内部链接或外部链接使用存储类说明符 static 来区分,使用了 static 的变量具有内部链接。最后,具有代码块作用域或函数原型作用域的变量有空链接,说明它们是私有的。
- 存储时期
一个变量具有以下两种存储时期之一:静态存储时期(static storage duration)和自动存储时期(automatic storage duration)。前者在程序执行期间将一直存在,比如具有文件作用域的变量具有静态存储时期,而不管其是否使用 static 关键字,static 只表明链接类型。具有代码块作用域的变量一般具有自动存储时期,可使用存储类说明符 auto 关键字表明。
存储类说明符
- auto:表明一个变量具有自动存储时期。只能用于具有代码块作用域的变量声明中,明确意图,提高程序易读性。
- extern:用于引用声明,即声明的变量已经在别处定义过了。
- register:也只能用于具有代码块作用域的变量。请求将该变量存储在一个寄存器内,以更快地存取。使用它后将不能获取变量的地址。
- static:用于表明链接类型,根据上下文而不同。
注意:绝不能在一个声明中使用一个以上的存储类说明符。
代码示例
// parta.c --- various storage classes
#include
void report_count();
void accumulate(int k);
int count = 0; // file scope, external linkage
int main(void)
{
int value; // automatic variable
register int i; // register variable
printf("Enter a positive integer (0 to quit): ");
while (scanf("%d", &value) == 1 && value > 0)
{
++count; // use file scope variable
for (i = value; i >= 0; i--)
accumulate(i);
printf("Enter a positive integer (0 to quit): ");
}
report_count();
return 0;
}
void report_count()
{
printf("Loop executed %d times\n", count);
}
// partb.c -- rest of the program
#include
extern int count; // reference declaration, external linkage
static int total = 0; // static definition, internal linkage
void accumulate(int k); // prototype
void accumulate(int k) // k has block scope, no linkage
{
static int subtotal = 0; // static, no linkage
if (k < = 0)
{
printf("loop cycle: %d\n", count);
printf("subtotal: %d; total: %d\n", subtotal, total);
subtotal = 0;
}
else
{
subtotal += k;
total += k;
}
}
小结
自动变量具有代码块作用域、空链接和自动存储时期。它们是局部变量,为定义它们的代码块(比如函数)所私有。寄存器变量和自动变量具有相同的属性,不同的是编译器
可能使用速度更快的内存或寄存器来存储它们,另外也无法获取一个寄存器的地址。
具有静态存储时期的变量可能具有外部链接、内部链接或空链接。这取决于声明变量的位置和是否使用关键字 static。
(本文内容来自《C Primer Plus》阅读笔记)