简介
在讲解C语言存储类型之前,需要明确几个概念。
作用域(scope):它描述了程序中可以访问一个标识符的一个或多个区域。
类型 说明 代码块作用域 在代码块中定义的变量(包括函数的形参)。 函数原型作用域 函数原型中的变量,如果在方括号中使用了变量名,则该变量名必须是在原型中已经声明的。例如: void use(int n, int m, int ar[n][m]);
此处方括号中的变量必须是原型中已经声明的。文件作用域 在所有函数之外定义的变量,从定义处到文件末尾均可见。 函数作用域 只适用于goto语句的标签,无论标签出现在哪一个代码块,该函数中的任何地方均可见。 链接(linkage):C语言变量具有三种链接。
类型 说明 空连接 具有代码块作用域或函数原型作用域的变量。 内部链接 具有文件作用域并拥有static存储类型说明符的变量。 外部链接 具有文件作用域不拥有static存储类型说明符的变量。 存储时期(storage duration):它是指一个数据对象在内存中的保留时间。存储时期可以分为两类。
类型 说明 静态存储时期 具有文件作用域的变量,该变量在程序执行期间一直存在。 自动存储时期 具有代码块作用域一般情况下具有自动存储时期(代码块内加static存储类型的变量除外)。程序在进入这些变量的定义时分配内存;退出代码块时释放内存。
C语言同作用域、链接和存储时期定义了以下5中存储类。
存储类 | 时期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 代码块 | 空 | 代码块内 |
寄存器 | 自动 | 代码块 | 空 | 代码块内,使用关键字register |
具有外部链接的静态 | 静态 | 文件 | 外部 | 所有函数之外 |
具有内部链接的静态 | 静态 | 文件 | 内部 | 所有函数之外,使用关键字static |
空链接的静态 | 静态 | 代码块 | 空 | 代码块内,使用关键字static |
存储类型说明符
C语言包含5中存储类型说明符,分别是typedef, extern, static, auto, register
。在声明过程中,最多只能指定一种存储类型说明符。
需要注意的是,typedef
被称为存储类型说明符仅仅是为了语义方便。同时,不可以在一个声明中指定一个以上的存储类型说明符。
关键字 | 说明 |
---|---|
auto | 表明变量具有自动存储时期,该说明符只能用在具有代码块作用域的变量声明中。 |
register | 请求将变量存在在寄存器内,该说明符只能用在具有代码块作用域的变量声明中,且不能获取变量的地址。 |
static | 该说明符用于代码块作用域的变量时,使得该变量具有静态存储时期,从而程序在运行期间将保存其值,但任具有代码块作用域和空连接;当用于文件作用域变量时,该变量具有内部链接。 |
extern | 表明已在别处定义了变量。如果包含extern的声明(引用声明)具有文件作用域,则所指向的变量必然具有外部链接;如果extern的声明具有代码块作用域,则所指向的变量可能具有外部链接也可能具有内部链接,取决于该变量的定义声明。 |
寄存器变量:声明一个寄存器变量仅仅是一个请求,编译器需要在您的请求与可用的寄存器个数或可用的高速缓存的数量之间做权衡,因此,可能在某些情况下,您可能达不成自己的愿望,此时寄存器变量变为一个普通的自动变量;由于寄存器变量多是存放在一个寄存器中,而不是内存中,因此无法对寄存器变量使用地址运算符。需要注意的是,可以使用register声明的类型是有限的。例如,寄存器没有足够大的控件来容纳该类型。
存储类和函数
函数同样具有存储类。函数可以是外部的(默认情况下)或者静态的(C99中增加了第三种内联函数)。外部函数可以被其他文件中的函数调用,而静态函数只可以在定义它的文件中使用。通常函数使用static存储类来创建一个特定模块所私有的函数,避免可能的名字冲突。