### 6. 存儲類型的關鍵字
**存儲類型定義 C 程序中變量/函數的范圍(可見性)和生命周期。這些說明符放置在它們所修飾的類型之前**。
存儲類型可以用于變量以及較小范圍的函數和形式參數的說明。**這一節的內容類似于Java中全局變量和局部變量的概念以及作用域,存儲范圍等知識點**
#### 變量的性質
C程序中的每個變量都具有以下3個性質。
* **存儲期限**。變量的存儲期限決定了為變量預留和內存被釋放的時間。
* 具有**自動存儲期限**的變量在所屬塊被執行時獲得內存單元,并在塊終止時釋放內存單元,從而會導致變量失去值。
* 具有**靜態存儲期限**的變量在程序運行期間占有同一個的非儲單元,也就允許變量無期限地保留它的值。
* **作用域**。變量的作用域是指可以引用變量的那部分程序文本。變量可以有**塊作用域**(變量從聲明的地方一直到所在塊的末尾都是可見的)或者**文件作用域**(變量從聲明的地方一直到所在文件的末尾都是可見的)。
* **鏈接**。變量的鏈接確定了程序的不同部分可以共享此變量的范圍。
* 具有**外部鏈接**的變量可以被程序中的幾個(或許全部)文件共享。
* 具有**內部鏈接**的變量只能屬于單獨一個文件,但是此文件中的函數可以共享這個變量。(如果具有相同名字的變量出現在另一個文件中,那么系統會把它作為不同的變量來處理。)
* **無鏈接**的變量屬于單獨一個函數,而且根本不能被共享。
**變量的默認存儲期限、作用域和鏈接都依賴于變量聲明的位置**。
* 在塊(包指函數體)內部聲明的變量具有自動存儲期限、塊作用域,并且無鏈接.
* 在程序的最外層(任意塊外部)聲明的變量有靜態存儲期限、文件作用域和外部鏈接。
下面的例子說明了變量i和變量j 的默認性質:

**對許多變量而言,默認的存儲期限、作用域和鏈接是符合要求的。當這些性質無法滿足要求時,可以通過指定明確的存儲類型(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
```
- 前言
- JNI基礎知識
- C語言知識點總結
- ①基本語法
- ②數據類型
- 枚舉類型
- 自定義類型(類型定義)
- ③格式化輸入輸出
- printf函數
- scanf函數
- 編程規范
- ④變量和常量
- 局部變量和外部變量
- ⑤類型轉換
- ⑥運算符
- ⑦結構語句
- 1、分支結構(選擇語句)
- 2、循環結構
- 退出循環
- break語句
- continue語句
- goto語句
- ⑧函數
- 函數的定義和調用
- 參數
- 函數的返回值
- 遞歸函數
- 零起點學通C語言摘要
- 內部函數和外部函數
- 變量存儲類別
- ⑨數組
- 指針
- 結構體
- 聯合體(共用體)
- 預處理器
- 預處理器的工作原理
- 預處理指令
- 宏定義
- 簡單的宏
- 帶參數的宏
- 預定義宏
- 文件包含
- 條件編譯
- 內存中的數據
- C語言讀文件和寫文件
- JNI知識點總結
- 前情回顧
- JNI規范
- jni開發
- jni開發中常見的錯誤
- JNI實戰演練
- C++(CPP)在Android開發中的應用
- 掘金網友總結的音視頻開發知識
- 音視頻學習一、C 語言入門
- 1.程序結構
- 2. 基本語法
- 3. 數據類型
- 4. 變量
- 5. 常量
- 6. 存儲類型關鍵字
- 7. 運算符
- 8. 判斷
- 9. 循環
- 10. 函數
- 11. 作用域規則
- 12. 數組
- 13. 枚舉
- 14. 指針
- 15. 函數指針與回調函數
- 16. 字符串
- 17. 結構體
- 18. 共用體
- 19. typedef
- 20. 輸入 & 輸出
- 21.文件讀寫
- 22. 預處理器
- 23.頭文件
- 24. 強制類型轉換
- 25. 錯誤處理
- 26. 遞歸
- 27. 可變參數
- 28. 內存管理
- 29. 命令行參數
- 總結
- 音視頻學習二 、C++ 語言入門
- 1. 基本語法
- 2. C++ 關鍵字
- 3. 數據類型
- 4. 變量類型
- 5. 變量作用域
- 6. 常量
- 7. 修飾符類型
- 8. 存儲類
- 9. 運算符
- 10. 循環
- 11. 判斷
- 12. 函數
- 13. 數學運算
- 14. 數組
- 15. 字符串
- 16. 指針
- 17. 引用
- 18. 日期 & 時間
- 19. 輸入輸出
- 20. 數據結構
- 21. 類 & 對象
- 22. 繼承
- 23. 重載運算符和重載函數
- 24. 多態
- 25. 數據封裝
- 26. 接口(抽象類)
- 27. 文件和流
- 28. 異常處理
- 29. 動態內存
- 30. 命名空間
- 31. 預處理器
- 32. 多線程
- 總結
- 音視頻學習 (三) JNI 從入門到掌握
- 音視頻學習 (四) 交叉編譯動態庫、靜態庫的入門學習
- 音視頻學習 (五) Shell 腳本入門
- 音視頻學習 (六) 一鍵編譯 32/64 位 FFmpeg 4.2.2
- 音視頻學習 (七) 掌握音頻基礎知識并使用 AudioTrack、OpenSL ES 渲染 PCM 數據
- 音視頻學習 (八) 掌握視頻基礎知識并使用 OpenGL ES 2.0 渲染 YUV 數據
- 音視頻學習 (九) 從 0 ~ 1 開發一款 Android 端播放器(支持多協議網絡拉流/本地文件)
- 音視頻學習 (十) 基于 Nginx 搭建(rtmp、http)直播服務器
- 音視頻學習 (十一) Android 端實現 rtmp 推流
- 音視頻學習 (十二) 基于 FFmpeg + OpenSLES 實現音頻萬能播放器
- 音視頻學習 (十三) Android 中通過 FFmpeg 命令對音視頻編輯處理(已開源)