C語言之static和extern關鍵字
1.作用域
識別符號可見的區域,訪問和重名
由宣告的位置所決定
1.1 程式碼塊作用域 Block Scope
-
花括號 {} 之內
-
函式形參(不會為函式內同名變數所隱藏)
```C void myFunction(int x) { int x = 10; // 這裡的 x 不會隱藏形參 x printf("%d\n", x); // 輸出的仍然是形參 x 的值 } ```
1.2 檔案作用域 file Scope
所有程式碼塊之外的識別符號
自宣告開始直到檔案尾
- 函式名
-
include展開可以擴充套件檔案尾,本質上就是字串替換
1.3 原型作用域 prototype Scope
僅適用於函式原型中宣告的引數名,該引數名並非必要的
1.4 函式作用域 Function Scope
僅適用於語句標籤,即goto語句
2.連結屬性
決定如何處理不同檔案中出現的識別符號
2.1 None
沒有連結屬性,多個宣告被認為是不同的獨立實體
區域性變數都是None
2.2 Internal 內部
同一個原始檔中所有宣告屬於同一個實體,不同原始檔宣告屬於不同實體
2.3 External 外部
無論宣告多少次都表示同一個實體,即全域性變數 Global
全域性 VS 區域性Local(僅僅是程式碼塊中?)
檔案作用域中的識別符號預設都是External,增加該關鍵字具有更好的可讀性
3.儲存型別
決定變數的生命週期
變數的預設儲存型別取決於宣告位置
- 程式碼塊之外,檔案作用域
- 靜態變數 static
- 靜態記憶體中
- 執行之前建立,在整個執行期間存在
- 初始化預設值為0,顯示初始化需要使用常量表示式,編譯時求值
- 程式碼塊之內,程式碼塊作用域
- 自動變數 auto (區域性變數 VS auto:static 修改儲存型別)
- 執行時堆疊
- 執行時建立,退出程式碼塊時銷燬
- 預設值無效,顯示初始化中除了使用const, 宣告時初始化和先宣告後賦值只有風格之差而無效率之別
- register修飾的自動變數
- 提示編譯器儲存在硬體暫存器中,不一定有效
- 週期和自動變數一樣,不使用地址
4.辨析
全域性變數 VS 區域性變數
- 作用域:程式碼塊的內部 VS 外部 (核心區別)
- 連結屬性:extern VS none
- 儲存型別:靜態記憶體 VS 執行時堆疊
靜態變數 VS 自動變數
- 變數物件:
- static修飾的區域性變數(狹義)和全域性變數(本質)
- 自動變數:無static修飾的區域性變數
- 儲存位置:
- 靜態變數儲存在靜態儲存區
- 自動變數儲存在棧區
- 生命週期:
- 靜態變數的生命週期是整個程式的執行期間,從程式開始執行到程式結束
- 自動變數的生命週期是在其所在的程式碼塊(如函式)被執行期間,當程式碼塊執行結束就被銷燬
- 初始化:
- 靜態變數在編譯時初始化,預設值為 0
- 自動變數在執行時初始化,預設值是未定義的
區域性變數預設為自動型別
- 執行時才分配儲存空間
- 在堆疊上方便實現遞迴
static不能修飾函式形參
- 不改變None連結屬性
- 不可改變儲存型別,引數透過堆疊傳遞
static和Extern關鍵字
- 修改連結屬性
- static只對預設為extern的識別符號有效
- 對 None型別不改變連結屬性
- extern 只對識別符號的第一次宣告有效
- static只對預設為extern的識別符號有效
Static 不影響作用域
- 程式碼塊之外:連結屬性改為 Internal
- 程式碼塊之內:儲存型別改為靜態記憶體
5.參考
- 《C和指標》
- 3.5 作用域
- 3.6 連結屬性
- 3.7 儲存型別
- 3.8 static 關鍵字
- 3.9 作用域、儲存型別示例
- 《嵌入式C語言的自我修養》
- 5.3.5 棧和作用域
- 《C程式設計語言》
- 1.10 外部變數與作用域
- 4.3 外部變數
- 4.4 作用域規則
- 4.6 靜態變數
- 4.7 暫存器變數
- 4.8 程式塊結構
- 4.9 初始化