C 語言

範圍與生存期

對程式中每個名字都會問兩個不同的問題。第一:在原始碼文字的哪裡我才被允許寫出這個名字?這是範圍——就像某張門禁卡能打開一棟建築的哪些房間。第二:在程式執行時,這個名字背後真正的儲存空間存在多久?這是生存期——就像那個房間本身租了多久。它們聽起來相似但並非同一個問題,把它們混淆會造成真正的錯誤。

範圍關乎程式碼中的可見性。在函式或 { } 區塊內宣告的變數具有區塊範圍:它只在從宣告到該區塊結尾之間可見,而內層區塊裡的名字可以遮蔽外層同名的名字。在所有函式之外宣告的名字具有檔案範圍:對該檔案其餘部分可見。生存期(儲存期)關乎執行期。典型的區域變數具有自動儲存期:進入區塊時建立它的儲存,離開區塊時銷毀。標記為 static 的變數,或位於檔案範圍的變數,具有靜態儲存期:它在整個程式執行期間都活著。

為什麼這個差別會咬人:一個區域變數可能這一行還在範圍內、下一行就消失了——而回傳這種變數的位址,或在其區塊結束後仍保留指向它的指標,就會得到指向已不存在儲存空間的懸置指標。相對地,靜態區域變數即使名字只在函式內可見,卻能在多次呼叫之間保留它的值。把範圍(編譯期概念)與生存期(執行期概念)清楚分開,是正確推理 C 的關鍵。

int g = 1; /* 檔案範圍,活整個程式 */ void f(void) { int local = 2; /* 區塊範圍,自動:到 } 就消失 */ static int calls = 0; /* 區塊範圍,但永遠活著 */ calls++; /* 跨呼叫記住它的值 */ }

local 與 calls 都只在 f 內可見(相同範圍),但 local 在右大括號處消亡,而 calls 在整個程式中持續(不同生存期)。

範圍是編譯期的可見性;生存期是執行期的存在——兩者獨立。回傳指向區域變數的指標,或在其區塊結束後使用它,會去解參考一塊已不存在的儲存(懸置指標)。

又称
visibility and storage duration可見範圍生命週期