儲存類
儲存類說明符是可以出現在宣告的頂級型別旁邊的關鍵字。這些關鍵字的使用會影響已宣告物件的儲存持續時間和連結,具體取決於它是在檔案範圍還是在塊範圍內宣告:
關鍵詞 | 儲存持續時間 | 連鎖 | 備註 |
---|---|---|---|
static |
靜態的 | 內部 | 為檔案範圍內的物件設定內部連結; 為塊範圍內的物件設定靜態儲存持續時間。 |
extern |
靜態的 | 外部 | 對於在檔案範圍中定義的物件(也具有初始化程式)隱含且因此是冗餘的。當在沒有初始化程式的檔案範圍的宣告中使用時,提示該定義將在另一個翻譯單元中找到,並將在連結時解析。 |
auto |
自動 | 不相干 | 隱含,因此對於在塊範圍內宣告的物件是多餘的。 |
register |
自動 | 不相干 | 僅與具有自動儲存持續時間的物件相關。提供變數應儲存在暫存器中的提示。強加的約束是不能在這樣的物件上使用一元 & 地址運算子,因此該物件不能被別名化。 |
typedef |
不相干 | 不相干 | 在實踐中不是儲存類說明符,但從語法的角度來看就像一個。唯一的區別是宣告的識別符號是一個型別,而不是一個物件。 |
_Thread_local |
線 | 內部外部 | 在 C11 中引入,表示執行緒儲存持續時間。如果在塊範圍內使用,它還應包括 extern 或 static 。 |
每個物件都有一個相關的儲存持續時間(無論範圍如何)和連結(僅與檔案範圍內的宣告相關),即使省略了這些關鍵字也是如此。
關於頂級型別說明符(int
,unsigned
,short
等)和頂級型別限定符(const
,volatile
)的儲存類說明符的順序未強制執行,因此這兩個宣告都是有效的:
int static const unsigned a = 5; /* bad practice */
static const unsigned int b = 5; /* good practice */
但是,將儲存類說明符放在首位,然後是任何型別限定符,然後是型別說明符(void
,char
,int
,signed long
,unsigned long long
,long double
……),這被認為是一種好習慣。
並非所有儲存類說明符在某個範圍內都是合法的:
register int x; /* legal at block scope, illegal at file scope */
auto int y; /* same */
static int z; /* legal at both file and block scope */
extern int a; /* same */
extern int b = 5; /* legal and redundant at file scope, illegal at block scope */
/* legal because typedef is treated like a storage class specifier syntactically */
int typedef new_type_name;
儲存持續時間
儲存持續時間可以是靜態的或自動的。對於宣告的物件,根據其範圍和儲存類說明符確定。
靜態儲存持續時間
具有靜態儲存持續時間的變數在整個程式執行期間都存在,並且可以在檔案範圍(有或沒有 static
)和塊範圍(通過明確地放置 static
)宣告。它們通常在程式啟動時由作業系統分配和初始化,並在程序終止時回收。在實踐中,可執行格式具有用於這些變數的專用部分(data
,bss
和 rodata
),並且來自檔案的這些整個部分被對映到特定範圍的儲存器中。
執行緒儲存持續時間
Version => C11
此儲存持續時間在 C11 中引入。這在早期的 C 標準中是不可用的。一些編譯器提供具有類似語義的非標準擴充套件。例如,gcc 支援 __thread
說明符,可以在早期的 C 標準中使用,它沒有 _Thread_local
。
具有執行緒儲存持續時間的變數可以在檔案範圍和塊範圍內宣告。如果在塊範圍內宣告,它還應使用 static
或 extern
儲存說明符。它的生命週期是整個執行它建立它的執行緒。這是唯一可以與另一個儲存說明符一起出現的儲存說明符。
自動儲存持續時間
具有自動儲存持續時間的變數只能在塊範圍內宣告(直接在函式內或在該函式的塊內)。它們僅在進入和離開功能或塊之間的時間段內可用。一旦變數超出範圍(通過從函式返回或離開塊),它的儲存將自動解除分配。從指標對同一變數的任何進一步引用都是無效的,並導致未定義的行為。
在典型的實現中,自動變數位於函式的堆疊幀中或暫存器中的某些偏移處。
外部和內部聯絡
連結僅與在檔案範圍內宣告的物件(函式和變數)相關,並影響它們在不同翻譯單元中的可見性。具有外部連結的物件在每個其他翻譯單元中都可見(前提是包含適當的宣告)。具有內部連結的物件不會暴露給其他翻譯單元,只能在定義它們的翻譯單元中使用。