声明中出现的存储类修饰符(storage class specifier)用于修改标识符的链接和对应对象的存储周期(链接与存储周期的概念将会在本章后面介绍)。
一个声明中不能出现多个存储类修饰符。函数标识符只可以使用存储类修饰符 extern 或 static。函数参数只可以使用存储类修饰符 register。5 种存储类修饰符的含义如下:
(1) auto
声明中有修饰符 auto 的对象,具有动态存储周期。这种修饰符只能用于函数内的对象声明。在 ANSIC 中,默认情况下函数内的对象声明都有动态的存储周期,所以不需要使用修饰符 auto。
(2) register
当声明对象有动态存储周期时,可以使用修饰符 register。该关键字告诉编译器,所声明对象的访问应该尽量快——理想情况下,应该将该对象存储在 CPU 寄存器(register)中。然而,编译器可能并不会按照理想情况那样做,而是会把用 register 声明的对象当成普通的动态存储周期对象。不管怎样,只要采用修饰符 re-gister 声明了对象,就不能用地址运算符对该对象进行操作。
(3) static
被声明为 static 的函数标识符具有内部链接,换句话说,别的翻译单元无法使用所声明的函数标识符来访问该函数。
被声明为 static 的对象标识符可能为外部链接,也可能为内部链接,至于是哪一种链接形式,取决于对象的定义是在函数内还是函数外。被声明为 static 的对象具有静态存储周期。因此,修饰符 static 允许定义局部对象(也就是具有语句块作用域的对象)为具有静态的存储周期。
(4) extern
被声明为 extern 的函数和对象标识符具有外部链接。可以在程序中任何地方使用这些标识符。外部对象具有静态的存储周期。
(5) _Thread_local
修饰符 _Thread_local 声明对象为线程局部(thread-local),表示每个线程都分别具有该对象的实例。只有对象能被声明为线程局部,而函数不能。如果在函数内部声明一个线程局部对象,声明必须具有修饰符 extern 或 static。在一个表达式中,线程局部对象的标识符引用当前线程中对象的本地实例,当前线程指当前计算该表达式的线程。