?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
指定對(duì)象和功能的存儲(chǔ)時(shí)間和鏈接:
auto
- 自動(dòng)持續(xù)時(shí)間和不連接
register
- 自動(dòng)持續(xù)時(shí)間,不需要鏈接; 這個(gè)變量的地址不能被采用
static
- 靜態(tài)持續(xù)時(shí)間和內(nèi)部聯(lián)系(除非在塊范圍內(nèi))
extern
- 靜態(tài)持續(xù)時(shí)間和外部聯(lián)系(除非已經(jīng)內(nèi)部聲明)
_Thread_local - thread storage duration | (since C11) |
---|
_Thread_local
- 線程存儲(chǔ)時(shí)間
(since C11)
存儲(chǔ)類說明符出現(xiàn)在聲明中。最多可以使用一個(gè)說明符,除了_Thread_local
可以結(jié)合static
或extern
調(diào)整結(jié)合(自C11以來)。存儲(chǔ)類說明符確定它們聲明的名稱的兩個(gè)獨(dú)立屬性:存儲(chǔ)持續(xù)時(shí)間和鏈接。
1)auto
說明符只允許在塊范圍聲明的對(duì)象(函數(shù)參數(shù)列表除外)。它表示自動(dòng)存儲(chǔ)持續(xù)時(shí)間并且沒有鏈接,這是這些類型的聲明的默認(rèn)值。
2)register
說明符僅適用于在塊范圍聲明的對(duì)象,包括函數(shù)參數(shù)列表。它指示自動(dòng)存儲(chǔ)持續(xù)時(shí)間并且沒有鏈接(這是這些類型的聲明的默認(rèn)值),但是另外提示優(yōu)化器在可能的情況下將該變量的值存儲(chǔ)在CPU寄存器中。無論這種優(yōu)化是否發(fā)生,聲明的變量register
都不能用作地址運(yùn)算符的參數(shù),不能使用alignas(因?yàn)镃11),并且register
數(shù)組不能用于指針轉(zhuǎn)換。
3)static
說明符同時(shí)指定靜態(tài)存儲(chǔ)持續(xù)時(shí)間(除非與_Thread_local
C11組合)和內(nèi)部鏈接(除非在塊范圍使用)。它可以與文件范圍內(nèi)的函數(shù)和文件和塊范圍內(nèi)的變量一起使用,但不能在函數(shù)參數(shù)列表中使用。
4)extern
說明符指定靜態(tài)存儲(chǔ)持續(xù)時(shí)間(除非與_Thread_local
C11結(jié)合)和外部鏈接。它可以在文件和塊范圍中使用函數(shù)和對(duì)象聲明(不包括函數(shù)參數(shù)列表)。如果extern
在重新聲明已經(jīng)用內(nèi)部鏈接聲明的標(biāo)識(shí)符時(shí)出現(xiàn),則鏈接保持內(nèi)部。否則(如果先前的聲明是外部的,無關(guān)聯(lián)的或不在范圍內(nèi)的話),該聯(lián)系是外部的。
5)_Thread_local表示線程的存儲(chǔ)時(shí)間。它不能用于函數(shù)聲明。如果它用于對(duì)象的聲明,則它必須出現(xiàn)在同一對(duì)象的每個(gè)聲明中。如果它在塊范圍聲明中使用,則必須將它與靜態(tài)或外部結(jié)合來決定鏈接。 | (自C11以來) |
---|
如果未提供存儲(chǔ)類說明符,則默認(rèn)值為:
extern
用于塊范圍內(nèi)extern
對(duì)象的文件范圍auto
對(duì)象的所有函數(shù)
對(duì)于使用存儲(chǔ)類說明符聲明的任何結(jié)構(gòu)體或聯(lián)合體,存儲(chǔ)持續(xù)時(shí)間(但不是鏈接)以遞歸方式適用于其成員。
塊范圍的函數(shù)聲明可以使用,extern
或者根本不使用。文件范圍的函數(shù)聲明可以使用extern
或static
。
函數(shù)參數(shù)不能使用除register
。以外的任何存儲(chǔ)類說明符。請(qǐng)注意,static
在數(shù)組類型的函數(shù)參數(shù)中有特殊含義。
每個(gè)對(duì)象都有一個(gè)稱為存儲(chǔ)時(shí)間的屬性,這會(huì)限制對(duì)象的生存期。C中有四種存儲(chǔ)持續(xù)時(shí)間:
自動(dòng)存儲(chǔ)時(shí)間。當(dāng)聲明對(duì)象的塊被輸入時(shí),存儲(chǔ)器被分配,當(dāng)通過任何方式(goto,return,end)結(jié)束時(shí),存儲(chǔ)器被分配。一個(gè)例外是VLA; 它們的存儲(chǔ)在執(zhí)行聲明時(shí)分配,而不是在塊入口處分配,并且當(dāng)聲明超出范圍時(shí),而不是在塊退出時(shí)(自C99以來)釋放。如果塊是遞歸輸入的,則為每個(gè)遞歸級(jí)別執(zhí)行新的分配。所有函數(shù)參數(shù)和非static
塊范圍對(duì)象都具有該存儲(chǔ)持續(xù)時(shí)間以及塊范圍中使用的復(fù)合文字。
靜態(tài)存儲(chǔ)時(shí)間。存儲(chǔ)持續(xù)時(shí)間是程序的整個(gè)執(zhí)行過程,存儲(chǔ)在對(duì)象中的值僅在main函數(shù)之前初始化一次。聲明的所有對(duì)象static
以及所有未聲明內(nèi)部或外部鏈接的對(duì)象_Thread_local
(自C11開始)具有此存儲(chǔ)期限。
線程存儲(chǔ)時(shí)間。存儲(chǔ)持續(xù)時(shí)間是創(chuàng)建它的線程的整個(gè)執(zhí)行過程,并且在線程啟動(dòng)時(shí)存儲(chǔ)在該對(duì)象中的值將被初始化。每個(gè)線程都有自己獨(dú)特的對(duì)象。如果執(zhí)行訪問此對(duì)象的表達(dá)式的線程不是執(zhí)行其初始化的線程,則該行為是實(shí)現(xiàn)定義的。所有聲明為_Thread_local的對(duì)象都有這個(gè)存儲(chǔ)期限。 | (自C11以來) |
---|
線程存儲(chǔ)時(shí)間。存儲(chǔ)持續(xù)時(shí)間是創(chuàng)建它的線程的整個(gè)執(zhí)行過程,并且在線程啟動(dòng)時(shí)存儲(chǔ)在該對(duì)象中的值將被初始化。每個(gè)線程都有自己獨(dú)特的對(duì)象。如果執(zhí)行訪問此對(duì)象的表達(dá)式的線程不是執(zhí)行其初始化的線程,則該行為是實(shí)現(xiàn)定義的。所有聲明的對(duì)象_Thread_local
都有這個(gè)存儲(chǔ)時(shí)間。
(since C11)
分配的存儲(chǔ)時(shí)間。根據(jù)請(qǐng)求使用動(dòng)態(tài)內(nèi)存分配功能分配和解除分配存儲(chǔ)空間。
連鎖是指在其他范圍內(nèi)引用標(biāo)識(shí)符(變量或函數(shù))的能力。如果具有相同標(biāo)識(shí)符的變量或函數(shù)在多個(gè)作用域中聲明,但不能從所有作用域中引用,則會(huì)生成多個(gè)變量實(shí)例。以下聯(lián)系被認(rèn)可:
沒有聯(lián)系。標(biāo)識(shí)符只能從其所在的范圍中引用。所有函數(shù)參數(shù)和所有非extern
塊范圍變量(包括已聲明的變量static
)都具有此關(guān)聯(lián)關(guān)系。
內(nèi)部聯(lián)系。標(biāo)識(shí)符可以從當(dāng)前翻譯單元中的所有范圍引用。所有的static
標(biāo)識(shí)符(包括函數(shù)和變量)都有這種聯(lián)系。
外部聯(lián)系。標(biāo)識(shí)符可以從整個(gè)程序中的任何其他翻譯單元引用。所有非static
函數(shù),所有extern
變量(除非更早聲明static
)和所有文件范圍非static
變量都具有此關(guān)聯(lián)。
如果相同的標(biāo)識(shí)符在同一翻譯單元中同時(shí)出現(xiàn)內(nèi)部和外部鏈接,則行為不確定。當(dāng)使用臨時(shí)定義時(shí),這是可能的。
具有外部鏈接的聲明通常在頭文件中可用,以便#include該文件的所有翻譯單元可以引用與別處定義的相同的標(biāo)識(shí)符。
出現(xiàn)在頭文件中的任何帶有內(nèi)部鏈接的聲明都會(huì)在包含該文件的每個(gè)翻譯單元中生成一個(gè)獨(dú)立且不同的對(duì)象。
庫接口:
// 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
庫實(shí)現(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)
應(yīng)用代碼:
// 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
.
關(guān)鍵字_Thread_local
通常通過thread_local
標(biāo)題中定義的便利宏使用threads.h
。
typedef說明符在C語言語法中正式列為存儲(chǔ)類說明符,但用于聲明類型名稱并且不指定存儲(chǔ)。
文件范圍中的名稱在C中const
沒有extern
外部鏈接(作為所有文件范圍聲明的默認(rèn)鏈接),但是在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