存储类
变量的基本内容
作用域(scope)
- 代码块作用域
- 函数原型作用域
- 文件作用域
存储时期(storage duration)
变量在内存中保留的时间。
- 静态存储时期(static storage duration)
- 能在程序执行期间一直存在。
- 自动存储时期(automatic storage duration)
- 在程序进入定义这些变量的代码块时,将为这些变量分配内存。
链接(linkage)
- 外部链接
- 可以在一个多文件程序的任何地方使用。
- 内部链接
- 可以在一个文件的任何地方使用。
- 空链接
- 意味着它们由其定义所在的代码块或函数原型所特有。
存储类说明符
auto
- 表明一个变量具有自动存储时期。只能在具有代码块作用域的变量声明中。主要是用来明确指出意图,使程序更易读。
register
- 把一个变量归入寄存器,相当于请求该变量存储在一个寄存器内,以更快地存取。它使用使你不能获得变量的地址。
static
- 使用在具有代码块作用域的变量声明时,使该变量具有静态存储时期,从而在程序运行期间,保留其值。只改变存储时期。
- 用于具有文件作用域的变量声明时,表明该变量具有内部链接。
extern
- 声明一个在别处已经有定义了的变量。
- 如果包含extern的声明具有文件作用域,所指向的变量必然具有外部链接。
- 如果包含extern的声明具有代码块作用域,所指向的变量可能具有外部链接也可能具有内部链接,着取决于该变量的定义声明。
存储类和函数
函数也具有存储类。
使用关键字static,则使这个函数只能被本文件使用,从而避免可能名字冲突。
使用关键字extern来声明其他文件中定义的函数。这个做法只是为了让程序更加清晰,因为除非函数声明用了关键字static,否则都认为他是extern的。
分类
自动变量(auto)
- 自动、代码块、空连接
- 相当于直接定义一个变量。如果为了表明有意覆盖一个外部函数定义时,或则为了表明不能把变量改变为其他存储类时,可以加上auto,作为强调的作用。
- 如果内层代码块定义了一个具有和外层代码块变量同一名字的变量,则内层定义会覆盖(hide)外部定义,但当运行离开内层代码块时,外部变量会重新恢复作用。
寄存器变量
- 自动、代码块、空(声明在代码块内,使用关键字register)
- 存储在寄存器里的变量能够更快地被访问和操作。但是声明一个寄存器类变量仅仅只是一个请求,并不一定能够实现,因为编译器会你的请求与可用寄存器的个数或可用高速内存的数量之间做权衡。
- 不管有没有申请成为寄存器变量,这个变量都不能被访问地址!而且register声明的类型是有限的,处理器可能没有足够大的寄存器来容纳double类型。
具有代码块作用域的静态变量(static)
- 静态、代码块、空链接
- “静态”是值变量的位置固定不动。
- 除了第一次以外,每一次进入函数作用域会自动忽略变量声明。
具有外部链接的静态(external variable)
- 静态、文件、外部
- 在所用函数以外,用extern定义。
- 外部变量在没有被赋值时,会自动被赋值为0。这一原则也适用于外部定义的数组元素。
- 定义和声明
- 第一次声明为变量留出了存储空间(也就是定义声明declaration)
- 第二次声明称为引用声明(referencing declaration). 关键词extern表明该声明不是一个定义,因为它指示编译器参考其他地方,可以是其他文件。
- 一个外部变量只可以进行一次初始化,而且一定是在变量被定义时进行的。
- 简单的说,就是在一个文件里定义的静态变量如果想要在别的文件里继续引用,就可以在其他文件里加extern声明。
具有内部链接的静态(static variable with internal linkage)
- 静态、文件、内部(声明在所有函数之外,使用关键字(static))
- 在全局变量的定义时,加上static关键词,这个变量会被定义为具有内部链接的静态变量(同理,如果不加static就会被定义为具有外部链接)。同样也可以用extern进行引用声明,但不改变变量的链接。
空链接的静态
- 静态、代码块、空(代码块内,使用关键字static)
多文件问题
- Rule1: 除非在第二个文件中也声明了该变量(extern),否则在一个文件中定义的外部变量不易用于第二个文件,一个外部变量声明本身只是使一个变量可能对其他文件可用。
- Rule 2: 除了定义声明外,其他所有声明都必须使用关键字extern,比且只有在定义声明中才可以对该变量进行初始化。