C の extern キーワード
この記事では、C 言語で extern
キーワードを使用する方法について複数の方法を示します。
他のファイルで定義された変数を C 言語で宣言するために extern
キーワードを使用する
一般的に、C 言語の変数には、外部リンケージ、内部リンケージ、無リンケージの 3 種類のリンケージがあります。ブロックスコープや関数スコープで変数が定義されている場合は、リンクがないとみなされます。ファイルスコープを持つ変数は、内部リンケージと外部リンケージを持つことができます。つまり、グローバル変数が static
修飾子で宣言されている場合、その変数は内部リンクを持ち、その変数が単一のソースファイル(より正確には翻訳単位)で使用できることを意味しています。static
修飾子を持たないグローバル変数は外部リンクを持ち、異なるソースファイルで使用できると考えられます。他のソースファイルで定義されたグローバル変数を使用するには、キーワード extern
を使って宣言しなければなりません。
#include <stdio.h>
#include <stdlib.h>
#ifndef COUNT
#define COUNT 10
#endif
extern int counter;
int main(void) {
printf("counter: ");
for (int i = 0; i < COUNT; ++i) {
counter += 1;
printf("%d, ", counter);
}
printf("\b\b \n");
exit(EXIT_SUCCESS);
}
出力:
counter: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
通常、extern
修飾された変数は別のファイルのどこかで定義されています。しかし、技術的には、以下の例のように、同じファイル内で extern
キーワードを使用してグローバル変数を宣言することができます。コンパイラは自動的に同じファイルスコープ内のどこにいても変数名が見えるようにするので、このタイプの宣言は基本的に冗長です。
#include <stdio.h>
#include <stdlib.h>
#ifndef COUNT
#define COUNT 10
#endif
int counter2 = 0;
int main(void) {
extern int counter2; // redundant
counter2 += 10;
printf("%d\n", counter2);
exit(EXIT_SUCCESS);
}
ただし、extern
宣言された変数は初期化すべきではないことに注意してください。同じ変数を const
修飾子を付けずに別のソースファイルで宣言しても、警告は出ずにコンパイルされ、オブジェクトの const 性が削除されます。したがって、ユーザが読み取り専用の文字列 tmp
を変更しようとした場合、コンパイラはエラーをスローしませんが、プログラムはセグメンテーションフォールトを起こします。
#include <stdio.h>
#include <stdlib.h>
#ifndef COUNT
#define COUNT 10
#endif
extern int counter;
// extern int counter = 3; // erroreous
extern char *tmp; // erroreous
int counter2 = 0;
int main(void) {
printf("counter: ");
for (int i = 0; i < COUNT; ++i) {
counter += 1;
printf("%d, ", counter);
}
printf("\b\b \n");
tmp[0] = 'S'; // segmentation fault
printf("%s", tmp);
exit(EXIT_SUCCESS);
}