儲存類說明符
指定物件和函式的儲存期和連結
auto
- 自動儲存期,無連結register
- 自動儲存期,無連結;此變數的地址不能被獲取static
- 靜態儲存期和內部連結(除非在塊作用域內)extern
- 靜態儲存期和外部連結(除非已宣告為內部連結)
|
(C11 起) |
目錄 |
[編輯] 解釋
儲存類說明符出現在宣告中和複合字面量表示式中(C23起)。最多可以使用一個說明符,但_Thread_local(C23前)thread_local(C23起)可以與static或extern結合以調整連結(C11起)。儲存類說明符決定它們宣告的名稱的兩個獨立屬性:儲存期和連結。
_Alignas
(C23前)alignas
(C23起)(C11起),並且register陣列不能轉換為指標。
5) _Thread_local(C23前)thread_local(C23起)指示執行緒儲存期。它不能用於函式宣告。如果它用於物件宣告,則它必須出現在同一物件的所有宣告中。如果它用於塊作用域宣告,則它必須與static或extern結合以決定連結。 |
(C11 起) |
如果沒有提供儲存類說明符,則預設值是
- 所有函式都為extern
- 檔案作用域的物件為extern
- 塊作用域的物件為auto
對於使用儲存類說明符宣告的任何結構體或聯合體,儲存期(而非連結)遞迴地應用於其成員。
塊作用域的函式宣告可以使用extern或不使用。檔案作用域的函式宣告可以使用extern或static。
函式引數不能使用除register之外的任何儲存類說明符。請注意,static在陣列型別的函式引數中具有特殊含義。
[編輯] 儲存期
每個物件都有一個名為儲存期的屬性,它限制了物件的生命週期。C中有四種儲存期
- 自動儲存期。當宣告物件的塊被進入時分配儲存,並在透過任何方式(goto、return、到達末尾)退出時解除分配。一個例外是VLA;它們的儲存在宣告執行時分配,而不是在塊進入時,並在宣告超出作用域時解除分配,而不是在塊退出時(C99起)。如果塊被遞迴進入,則每個遞迴級別都會執行新的分配。所有函式引數和非static塊作用域物件都具有此儲存期,以及在塊作用域中使用的複合字面量(C23前)
- 靜態儲存期。儲存期是程式的整個執行過程,並且物件中儲存的值只初始化一次,在main函式之前。所有宣告為static的物件以及所有具有內部或外部連結但未宣告為_Thread_local(C23前)thread_local(C23起)(C11起)的物件都具有此儲存期。
|
(C11 起) |
- 分配儲存期。使用動態記憶體分配函式,根據請求分配和解除分配儲存。
[編輯] 連結
連結指的是識別符號(變數或函式)在其他作用域中被引用的能力。如果一個具有相同識別符號的變數或函式在多個作用域中宣告,但不能從所有作用域中被引用,那麼會生成該變數的多個例項。識別以下連結
- 無連結。變數或函式只能從其所在的作用域(塊作用域)中引用。所有未宣告為
extern
的塊作用域變數,以及所有函式引數和所有非函式或變數的識別符號都具有此連結。
- 無連結。變數或函式只能從其所在的作用域(塊作用域)中引用。所有未宣告為
- 內部連結。變數或函式可以從當前翻譯單元中的所有作用域中引用。所有宣告為
static
或constexpr
(C23起)的檔案作用域變數都具有此連結,以及所有宣告為static
的檔案作用域函式(靜態函式宣告只允許在檔案作用域)。
- 內部連結。變數或函式可以從當前翻譯單元中的所有作用域中引用。所有宣告為
- 外部連結。變數或函式可以從整個程式中的任何其他翻譯單元中引用。所有未宣告為
static
或constexpr
(C23起)的檔案作用域變數都具有此連結,所有未宣告為static
的檔案作用域函式宣告,所有塊作用域函式宣告,以及,如果之前沒有可見的內部連結宣告,所有宣告為extern
的變數或函式都具有此連結。
- 外部連結。變數或函式可以從整個程式中的任何其他翻譯單元中引用。所有未宣告為
如果同一識別符號在同一翻譯單元中同時出現內部連結和外部連結,則行為是未定義的。這在使用了暫定定義時可能發生。
[編輯] 連結和庫
本節不完整 原因:這應該作為c/language下“雜項”中的一個獨立的頂級條目嗎? |
具有外部連結的宣告通常在標頭檔案中提供,以便所有#include該檔案的翻譯單元都可以引用在其他地方定義的相同識別符號。
任何出現在標頭檔案中的具有內部連結的宣告都會在每個包含該檔案的翻譯單元中產生一個單獨且不同的物件。
庫介面,標頭檔案 "flib.h" #ifndef FLIB_H #define FLIB_H void f(void); // function declaration with external linkage extern int state; // variable declaration with external linkage static const int size = 5; // definition of a read-only variable with internal linkage enum { MAX = 10 }; // constant definition inline int sum (int a, int b) { return a + b; } // inline function definition #endif // FLIB_H 庫實現,原始檔 "flib.c" #include "flib.h" static void local_f(int s) {} // definition with internal linkage (only used in this file) static int local_state; // definition with internal linkage (only used in this file) int state; // definition with external linkage (used by main.c) void f(void) { local_f(state); } // definition with external linkage (used by main.c) 應用程式程式碼,原始檔 "main.c" #include "flib.h" int main(void) { int x[MAX] = {size}; // uses the constant and the read-only variable state = 7; // modifies state in flib.c f(); // calls f() in flib.c } |
[編輯] 關鍵詞
auto, register, static, extern, _Thread_local thread_local
[編輯] 注意
關鍵字_Thread_local通常透過便利宏thread_local使用,該宏定義在標頭檔案<threads.h>中。 |
(直至 C23) |
typedef
和constexpr
(C23起)說明符在C語言語法中形式上被列為儲存類說明符,但它們不指定儲存。
auto說明符也用於型別推斷。 |
(自 C23 起) |
檔案作用域中宣告為const且不是extern的名稱在C中具有外部連結(作為所有檔案作用域宣告的預設值),但在C++中具有內部連結。
[編輯] 示例
#include <stdio.h> #include <stdlib.h> // static storage duration int A; int main(void) { printf("&A = %p\n", (void*)&A); // automatic storage duration int A = 1; // hides global A printf("&A = %p\n", (void*)&A); // allocated storage duration int* ptr_1 = malloc(sizeof(int)); // start allocated storage duration printf("address of int in allocated memory = %p\n", (void*)ptr_1); free(ptr_1); // stop allocated storage duration }
可能的輸出
&A = 0x600ae4 &A = 0x7ffefb064f5c address of int in allocated memory = 0x1f28c30
[編輯] 參考
- C23 標準 (ISO/IEC 9899:2024)
- 6.2.2 識別符號的連結 (p: 35-36)
- 6.2.4 物件的儲存期 (p: 36-37)
- 6.7.1 儲存類說明符 (p: 97-100)
- C17 標準 (ISO/IEC 9899:2018)
- 6.2.2 識別符號的連結 (p: 29-30)
- 6.2.4 物件的儲存期 (p: 30)
- 6.7.1 儲存類說明符 (p: 79)
- C11 標準 (ISO/IEC 9899:2011)
- 6.2.2 識別符號的連結 (p: 36-37)
- 6.2.4 物件的儲存期 (p: 38-39)
- 6.7.1 儲存類說明符 (p: 109-110)
- C99 標準 (ISO/IEC 9899:1999)
- 6.2.2 識別符號的連結 (p: 30-31)
- 6.2.4 物件的儲存期 (p: 32)
- 6.7.1 儲存類說明符 (p: 98-99)
- C89/C90 標準 (ISO/IEC 9899:1990)
- 3.1.2.2 識別符號的連結
- 3.1.2.4 物件的儲存期
- 3.5.1 儲存類說明符
[編輯] 另請參閱
C++ 文件,關於儲存類說明符
|