関数定義とシンボル宣言という2つの異なる概念を区別する必要があります。「extern」はリンケージ修飾子であり、後で参照されるシンボルが定義されている場所に関するコンパイラへのヒントです(ヒントは「ここではありません」)。
私が書いたら
extern int i;
Cファイルのファイルスコープ(関数ブロックの外)では、「変数は他の場所で定義されている可能性があります」と言っています。
extern int f() {return 0;}
関数fの宣言と関数fの定義の両方です。この場合の定義は、externをオーバーライドします。
extern int f();
int f() {return 0;}
は最初の宣言で、その後に定義が続きます。
extern
ファイルスコープ変数を宣言し、同時に定義する場合は、使用方法が間違っています。例えば、
extern int i = 4;
コンパイラに応じて、エラーまたは警告が表示されます。
の使用はextern
、変数の定義を明示的に避けたい場合に役立ちます。
説明させてください:
acファイルに次の内容が含まれているとします。
#include "a.h"
int i = 2;
int f() { i++; return i;}
ファイルああが含まれています:
extern int i;
int f(void);
そして、ファイルbcは以下を含みます:
#include <stdio.h>
#include "a.h"
int main(void){
printf("%d\n", f());
return 0;
}
ヘッダーのexternは、リンク段階でコンパイラに「これは宣言であり、定義ではない」ことを伝えるので、役に立ちます。acでiを定義している行を削除し、そのためのスペースを割り当てて、それに値を割り当てた場合、プログラムは未定義の参照でコンパイルに失敗するはずです。これは、変数を参照したが、まだ定義していないことを開発者に知らせます。一方、「extern」キーワードを省略してint i = 2
行を削除しても、プログラムは引き続きコンパイルされます-iはデフォルト値0で定義されます。
関数の先頭で宣言するブロックスコープ変数とは異なり、明示的に値を割り当てない場合、ファイルスコープ変数は暗黙的にデフォルト値0またはNULLで定義されます。externキーワードは、この暗黙の定義を回避するため、間違いを回避するのに役立ちます。
関数の場合、関数宣言では、キーワードは実際に冗長です。関数宣言には暗黙の定義はありません。