🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 6. 存储类型的关键字 **存储类型定义 C 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前**。 存储类型可以用于变量以及较小范围的函数和形式参数的说明。**这一节的内容类似于Java中全局变量和局部变量的概念以及作用域,存储范围等知识点** #### 变量的性质 C程序中的每个变量都具有以下3个性质。 * **存储期限**。变量的存储期限决定了为变量预留和内存被释放的时间。 * 具有**自动存储期限**的变量在所属块被执行时获得内存单元,并在块终止时释放内存单元,从而会导致变量失去值。 * 具有**静态存储期限**的变量在程序运行期间占有同一个的非储单元,也就允许变量无期限地保留它的值。 * **作用域**。变量的作用域是指可以引用变量的那部分程序文本。变量可以有**块作用域**(变量从声明的地方一直到所在块的末尾都是可见的)或者**文件作用域**(变量从声明的地方一直到所在文件的末尾都是可见的)。 * **链接**。变量的链接确定了程序的不同部分可以共享此变量的范围。 * 具有**外部链接**的变量可以被程序中的几个(或许全部)文件共享。 * 具有**内部链接**的变量只能属于单独一个文件,但是此文件中的函数可以共享这个变量。(如果具有相同名字的变量出现在另一个文件中,那么系统会把它作为不同的变量来处理。) * **无链接**的变量属于单独一个函数,而且根本不能被共享。 **变量的默认存储期限、作用域和链接都依赖于变量声明的位置**。 * 在块(包指函数体)内部声明的变量具有自动存储期限、块作用域,并且无链接. * 在程序的最外层(任意块外部)声明的变量有静态存储期限、文件作用域和外部链接。 下面的例子说明了变量i和变量j 的默认性质: ![](https://img.kancloud.cn/c3/8c/c38c6377a77df095533ce963239d4b9d_382x381.png) **对许多变量而言,默认的存储期限、作用域和链接是符合要求的。当这些性质无法满足要求时,可以通过指定明确的存储类型(auto 、static 、extern和register)来改变变量的性质**。 下面列出 C 程序中可用的存储类: * auto * register * static * extern #### auto 存储类 auto 存储类是**所有局部变量默认的存储类**。 ``` int month; auto int month; ``` 上面定义了两个带有相同存储类,auto 只能用在函数内,即 auto 只能修饰局部变量。 #### register 存储类 **register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)**。 ``` register int miles; ``` 寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,**定义 register并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制**。 #### static 存储类 **static 存储类指示编译器在程序的生命周期内保持局部变量的存在**,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,**使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内**。 **全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中**。 例子: ``` //函数声明 void func1(void); static int count = 10; //全局变量 - static 默认的 void main() { while (count--) { func1(); } } void func1(void) { // 'thingy' 是 'func1' 的局部变量 - 只初始化一次 // * 每次调用函数 'func1' 'thingy' 值不会被重置。 static int thingy = 5; thingy++; printf("thingy 为 %d, count 为 %d \n", thingy, count); } ``` 输出: ``` thingy 为 6, count 为 9 thingy 为 7, count 为 8 thingy 为 8, count 为 7 thingy 为 9, count 为 6 thingy 为 10, count 为 5 thingy 为 11, count 为 4 thingy 为 12, count 为 3 thingy 为 13, count 为 2 thingy 为 14, count 为 1 thingy 为 15, count 为 0 ``` 实例中 count 作为全局变量可以在函数内使用,thingy 在局部使用 static 修饰后,不会在每次调用时重置。 #### extern 存储类 extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。 当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。 extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候,如下所示: 第一个文件 ndk_day1.c ``` #include //stdio.h 是一个头文件(标准输入输出头文件),#include 是一个预处理命令,用来引入头文件。 #include "support.h" //引入自己的头文件 int main() {     int sum = add(2, 5);     printf("extern 使用 :%d", sum); } ``` 声明 support.h 头文件 ``` // // Created by 阳坤 on 2019/12/13. // #ifndef NDK_SAMPLE_SUPPORT_H #define NDK_SAMPLE_SUPPORT_H #endif //NDK_SAMPLE_SUPPORT_H extern int add(int num1,int num2); ``` 头文件的实现 support.c ``` int add(int num1,int num2){ return num1 * num2; } ``` 输出: ``` extern 使用 :10 ```