extern 關鍵字可以套用至全域變數、函式或範本宣告。 此關鍵字指定符號具有外部連結。 如需連結的背景資訊,以及為何不建議使用全域變數,請參閱編譯單位和連結。
extern 關鍵字有四個意義,視內容而定:
在非
const全域變數宣告中,extern指定變數或函式定義在另一個編譯單位中。extern必須套用在所有檔案中,但定義變數的檔案除外。在
const變數宣告中,指定變數具有外部連結。extern必須套用至所有檔案中的所有宣告。 (全域const變數預設具有內部連結。)extern "C"指定函式定義於其他地方,並使用 C 語言呼叫慣例。extern "C"修飾元也可以套用至區塊中的多個函式宣告。在範本宣告中,
extern指定範本已在其他地方具現化。extern告訴編譯器可以重複使用另一個具現化,而不是在目前位置建立新的。 如需extern用法的詳細資訊,請參閱明確具現化。
非 extern 全域的 const 連結
當連結器在全域變數宣告之前看到 extern 時,其會在另一個編譯單位中尋找定義。 預設情況下,全域範圍內的非 const 變數宣告是外部的。 僅將 extern 套用於未提供定義的聲明。
//fileA.cpp
int i = 42; // declaration and definition
//fileB.cpp
extern int i; // declaration only. same as i in FileA
//fileC.cpp
extern int i; // declaration only. same as i in FileA
//fileD.cpp
int i = 43; // LNK2005! 'i' already has a definition.
extern int i = 43; // same error (extern is ignored on definitions)
extern 全域的 const 連結
預設下 const 全域變數預設具有內部連結。 如果希望變數具有外部連結,請將 extern 關鍵字套用到定義和其他檔案中的所有其他宣告:
//fileA.cpp
extern const int i = 42; // extern const definition
//fileB.cpp
extern const int i; // declaration only. same as i in FileA
extern constexpr 連結
在 Visual Studio 2017 版本 15.3 及更早版本中,編譯器一律會為 constexpr 變數提供內部連結,即使變數標記為 extern 也一樣。 在 Visual Studio 2017 15.5 版本和更新版本中,編譯器參數 /Zc:externConstexpr 可實現正確且符合標準的行為。 該選項最終會成為預設選項。
/permissive- 選項不會啟用 /Zc:externConstexpr。
extern constexpr int x = 10; //error LNK2005: "int const x" already defined
如果標頭檔包含宣告為 externconstexpr 的變數,就必須以 __declspec(selectany) 標記,才能正確地合併其重複宣告:
extern constexpr __declspec(selectany) int x = 10;
extern "C" 和 extern "C++" 的函式宣告
在 C++ 中,搭配字串使用時,extern 會將其他語言的連結慣例指定為供宣告子使用。 只有在先前宣告為具有 C 連結時,才可以存取 C 函式和資料。 不過,您必須在另行編譯的轉譯單位中定義它們。
Microsoft C++ 在 "C" 欄位中支援字串 "C++" 和 。 所有使用 extern "C" 語法的標準 include 檔案都可在 C++ 程式中使用執行階段程式庫函式。
範例
下列範例顯示宣告具有 C 連結之名稱的替代方式:
// Declare printf with C linkage.
extern "C" int printf(const char *fmt, ...);
// Cause everything in the specified
// header files to have C linkage.
extern "C" {
// add your #include statements here
#include <stdio.h>
}
// Declare the two functions ShowChar
// and GetChar with C linkage.
extern "C" {
char ShowChar(char ch);
char GetChar(void);
}
// Define the two functions
// ShowChar and GetChar with C linkage.
extern "C" char ShowChar(char ch) {
putchar(ch);
return ch;
}
extern "C" char GetChar(void) {
char ch;
ch = getchar();
return ch;
}
// Declare a global variable, errno, with C linkage.
extern "C" int errno;
如果函式有多個連結規格,則這些規格必須相同。 宣告函式同時具有 C 和 C++ 連結是錯誤的。 此外,如果程式中的一個函式發生兩次宣告 (一個使用連結規格,另一個沒有),則使用連結規格的宣告必須是第一個。 第一個宣告會針對任何已經有連結規格的其餘函式宣告指定連結。 例如:
extern "C" int CFunc1();
...
int CFunc1(); // Redeclaration is benign; C linkage is
// retained.
int CFunc2();
...
extern "C" int CFunc2(); // Error: not the first declaration of
// CFunc2; cannot contain linkage
// specifier.
從 Visual Studio 2019 開始,指定 /permissive- 時,編譯程式會檢查 extern "C" 函式參數的宣告也相符。 您無法多載宣告為 extern "C" 的函式。 從 Visual Studio 2019 16.3 版開始,您可以在 /Zc:externC- 選項之後使用 /permissive- 編譯器選項來覆寫此檢查。