extern
(C++)
キーワード extern
は、グローバル変数、関数、またはテンプレート宣言に適用できます。 これは、シンボルが external リンケージを持つことを示します。 リンケージの背景情報と、グローバル変数の使用が推奨される理由については、「翻訳単位とリンケージ」を参照してください。
キーワード extern
には、コンテキストに応じて 4 つの意味があります。
非
const
グローバル変数宣言では、extern
によって変数または関数が別の翻訳単位で定義されることが指定されます。 変数が定義されているファイルを除くすべてのファイルで、extern
を適用する必要があります。変数宣言
const
では、変数に extern al リンケージがあることを指定します。extern
は、すべてのファイル内のすべての宣言に適用する必要があります。 (グローバルconst
変数には既定で内部リンケージがあります)。extern "C"
は、関数が他の場所で定義され、C 言語呼び出し規則を使用することを指定します。extern "C"
修飾子は、ブロック内の複数の関数宣言にも適用できます。テンプレート宣言で、
extern
は、テンプレートが既に他の場所でインスタンス化済みである場合に指定します。extern
からコンパイラに、現在の場所に新しいインスタンスを作成するのではなく、他のインスタンス化を再利用できると指示されます。 このextern
の使い方については、「明示的なインスタンス化」を参照してください。
非 const
グローバルの extern
リンケージ
リンカーは、グローバル変数宣言の前に extern
が表示された場合、別の翻訳単位で定義を参照します。 既定では、グローバル スコープでの非 const
変数の宣言は、external です。 定義を提供しない宣言にのみ 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)
const
グローバルの extern
リンケージ
既定では、const
グローバル変数には内部リンケージがあります。 変数に external リンケージを設定する場合は、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
リンケージ
2017 Visual Studio 15.3 以前では、変数が extern
とマークされている場合でも、コンパイラは常に constexpr
変数内部リンケージを指定しました。 Visual Studio 2017 バージョン 15.5 以降、コンパイラ スイッチ (/Zc:externConstexpr
) により、正しい標準準拠の動作が可能になります。 最終的にこの動作は既定値になります。 /permissive-
オプションでは、/Zc:externConstexpr
は有効になりません。
extern constexpr int x = 10; //error LNK2005: "int const x" already defined
ヘッダー ファイルには、宣言された変数 extern
constexpr
が含まれている場合、重複する宣言を正しく組み合わせるために、必ず __declspec(selectany)
のマークを付ける必要があります。
extern constexpr __declspec(selectany) int x = 10;
extern "C"
と extern "C++"
関数宣言
C++ では、文字列を使用する場合、extern
により、別の言語のリンケージ規則が宣言に使用されることが示されます。 C の関数とデータには、C リンケージを持つと以前に宣言されている場合にのみ、アクセスできます。 ただし、別にコンパイルされた翻訳単位で定義する必要があります。
Microsoft C++ は string-literal フィールドで文字列 "C"
と "C++"
をサポートします。 すべての標準の include ファイルは、extern "C"
構文を使用して、ランタイム ライブラリ関数が 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++ の両方のリンケージを持つとして宣言するとエラーになります。 また、プログラム内にリンケージ指定子を含むものと、含まない 2 つの関数宣言がある場合、リンケージ指定子を含む宣言を最初に記述する必要があります。 既にリンケージ指定を持つ関数の冗長な宣言には、最初の宣言で指定したリンケージが与えられます。 次に例を示します。
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 以降、/permissive-
オプションの後に /Zc:externC-
コンパイラ オプションを使用することで、このチェックをオーバーライドできます。
関連項目
キーワード
翻訳単位とリンケージ
extern ストレージ クラス指定子 (C)
C での識別子の動作
C でのリンケージ
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示