?
? ????? PHP ??? ???? ??? ?? ??
指定對象和功能的存儲時間和鏈接:
auto
- 自動持續(xù)時間和不連接
register
- 自動持續(xù)時間,不需要鏈接; 這個變量的地址不能被采用
static
- 靜態(tài)持續(xù)時間和內(nèi)部聯(lián)系(除非在塊范圍內(nèi))
extern
- 靜態(tài)持續(xù)時間和外部聯(lián)系(除非已經(jīng)內(nèi)部聲明)
_Thread_local - thread storage duration | (since C11) |
---|
_Thread_local
- 線程存儲時間
(since C11)
存儲類說明符出現(xiàn)在聲明中。最多可以使用一個說明符,除了_Thread_local
可以結合static
或extern
調(diào)整結合(自C11以來)。存儲類說明符確定它們聲明的名稱的兩個獨立屬性:存儲持續(xù)時間和鏈接。
1)auto
說明符只允許在塊范圍聲明的對象(函數(shù)參數(shù)列表除外)。它表示自動存儲持續(xù)時間并且沒有鏈接,這是這些類型的聲明的默認值。
2)register
說明符僅適用于在塊范圍聲明的對象,包括函數(shù)參數(shù)列表。它指示自動存儲持續(xù)時間并且沒有鏈接(這是這些類型的聲明的默認值),但是另外提示優(yōu)化器在可能的情況下將該變量的值存儲在CPU寄存器中。無論這種優(yōu)化是否發(fā)生,聲明的變量register
都不能用作地址運算符的參數(shù),不能使用alignas(因為C11),并且register
數(shù)組不能用于指針轉(zhuǎn)換。
3)static
說明符同時指定靜態(tài)存儲持續(xù)時間(除非與_Thread_local
C11組合)和內(nèi)部鏈接(除非在塊范圍使用)。它可以與文件范圍內(nèi)的函數(shù)和文件和塊范圍內(nèi)的變量一起使用,但不能在函數(shù)參數(shù)列表中使用。
4)extern
說明符指定靜態(tài)存儲持續(xù)時間(除非與_Thread_local
C11結合)和外部鏈接。它可以在文件和塊范圍中使用函數(shù)和對象聲明(不包括函數(shù)參數(shù)列表)。如果extern
在重新聲明已經(jīng)用內(nèi)部鏈接聲明的標識符時出現(xiàn),則鏈接保持內(nèi)部。否則(如果先前的聲明是外部的,無關聯(lián)的或不在范圍內(nèi)的話),該聯(lián)系是外部的。
5)_Thread_local表示線程的存儲時間。它不能用于函數(shù)聲明。如果它用于對象的聲明,則它必須出現(xiàn)在同一對象的每個聲明中。如果它在塊范圍聲明中使用,則必須將它與靜態(tài)或外部結合來決定鏈接。 | (自C11以來) |
---|
如果未提供存儲類說明符,則默認值為:
extern
用于塊范圍內(nèi)extern
對象的文件范圍auto
對象的所有函數(shù)
對于使用存儲類說明符聲明的任何結構體或聯(lián)合體,存儲持續(xù)時間(但不是鏈接)以遞歸方式適用于其成員。
塊范圍的函數(shù)聲明可以使用,extern
或者根本不使用。文件范圍的函數(shù)聲明可以使用extern
或static
。
函數(shù)參數(shù)不能使用除register
。以外的任何存儲類說明符。請注意,static
在數(shù)組類型的函數(shù)參數(shù)中有特殊含義。
每個對象都有一個稱為存儲時間的屬性,這會限制對象的生存期。C中有四種存儲持續(xù)時間:
自動存儲時間。當聲明對象的塊被輸入時,存儲器被分配,當通過任何方式(goto,return,end)結束時,存儲器被分配。一個例外是VLA; 它們的存儲在執(zhí)行聲明時分配,而不是在塊入口處分配,并且當聲明超出范圍時,而不是在塊退出時(自C99以來)釋放。如果塊是遞歸輸入的,則為每個遞歸級別執(zhí)行新的分配。所有函數(shù)參數(shù)和非static
塊范圍對象都具有該存儲持續(xù)時間以及塊范圍中使用的復合文字。
靜態(tài)存儲時間。存儲持續(xù)時間是程序的整個執(zhí)行過程,存儲在對象中的值僅在main函數(shù)之前初始化一次。聲明的所有對象static
以及所有未聲明內(nèi)部或外部鏈接的對象_Thread_local
(自C11開始)具有此存儲期限。
線程存儲時間。存儲持續(xù)時間是創(chuàng)建它的線程的整個執(zhí)行過程,并且在線程啟動時存儲在該對象中的值將被初始化。每個線程都有自己獨特的對象。如果執(zhí)行訪問此對象的表達式的線程不是執(zhí)行其初始化的線程,則該行為是實現(xiàn)定義的。所有聲明為_Thread_local的對象都有這個存儲期限。 | (自C11以來) |
---|
線程存儲時間。存儲持續(xù)時間是創(chuàng)建它的線程的整個執(zhí)行過程,并且在線程啟動時存儲在該對象中的值將被初始化。每個線程都有自己獨特的對象。如果執(zhí)行訪問此對象的表達式的線程不是執(zhí)行其初始化的線程,則該行為是實現(xiàn)定義的。所有聲明的對象_Thread_local
都有這個存儲時間。
(since C11)
分配的存儲時間。根據(jù)請求使用動態(tài)內(nèi)存分配功能分配和解除分配存儲空間。
連鎖是指在其他范圍內(nèi)引用標識符(變量或函數(shù))的能力。如果具有相同標識符的變量或函數(shù)在多個作用域中聲明,但不能從所有作用域中引用,則會生成多個變量實例。以下聯(lián)系被認可:
沒有聯(lián)系。標識符只能從其所在的范圍中引用。所有函數(shù)參數(shù)和所有非extern
塊范圍變量(包括已聲明的變量static
)都具有此關聯(lián)關系。
內(nèi)部聯(lián)系。標識符可以從當前翻譯單元中的所有范圍引用。所有的static
標識符(包括函數(shù)和變量)都有這種聯(lián)系。
外部聯(lián)系。標識符可以從整個程序中的任何其他翻譯單元引用。所有非static
函數(shù),所有extern
變量(除非更早聲明static
)和所有文件范圍非static
變量都具有此關聯(lián)。
如果相同的標識符在同一翻譯單元中同時出現(xiàn)內(nèi)部和外部鏈接,則行為不確定。當使用臨時定義時,這是可能的。
具有外部鏈接的聲明通常在頭文件中可用,以便#include該文件的所有翻譯單元可以引用與別處定義的相同的標識符。
出現(xiàn)在頭文件中的任何帶有內(nèi)部鏈接的聲明都會在包含該文件的每個翻譯單元中生成一個獨立且不同的對象。
庫接口:
// flib.h#ifndef FLIB_H #define FLIB_Hvoid f(void); // function declaration with external linkageextern int state; // variable declaration with external linkagestatic const int size = 5; // definition of a read-only variable with internal linkageenum { MAX = 10 }; // constant definitioninline int sum (int a, int b) { return a+b; } // inline function definition#endif // FLIB_H
庫實現(xiàn):
// 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
標題中定義的便利宏使用threads.h
。
typedef說明符在C語言語法中正式列為存儲類說明符,但用于聲明類型名稱并且不指定存儲。
文件范圍中的名稱在C中const
沒有extern
外部鏈接(作為所有文件范圍聲明的默認鏈接),但是在C ++中是內(nèi)部鏈接。
C11 standard (ISO/IEC 9899:2011):
6.2.2 Linkages of identifiers (p: 36-37)
6.2.4 Storage durations of objects (p: 38-39)
6.7.1 Storage-class specifiers (p: 109-110)
C99 standard (ISO/IEC 9899:1999):
6.2.2 Linkages of identifiers (p: 30-31)
6.2.4 Storage durations of objects (p: 32)
6.7.1 Storage-class specifiers (p: 98-99)
C89/C90 standard (ISO/IEC 9899:1990):
3.1.2.2 Linkages of identifiers
3.1.2.4 Storage durations of objects
3.5.1 Storage-class specifiers