何年か後、私はこの問題を発見しました。すべての回答とコメントを読んだ後、いくつかの詳細を明確にできると思いました...これは、Google検索でここにたどり着く人にとって便利かもしれません。
問題は特に「extern」関数の使用に関するものであるため、グローバル変数での「extern」の使用は無視します。
3つの関数プロトタイプを定義しましょう:
//--------------------------------------
//Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
int function_3(void);
ヘッダーファイルは、次のようにメインソースコードで使用できます。
//--------------------------------------
//Filename: "my_project.C"
#include "my_project.H"
void main(void){
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 1234;
コンパイルしてリンクするには、その関数を呼び出すのと同じソースコードファイルで "function_2"を定義する必要があります。他の2つの関数は、異なるソースコード " .C"で定義することも、ソースコードがないバイナリファイル( .OBJ、*。LIB、*。DLL)に配置することもできます。
違いをよく理解するために、別の「* .C」ファイルにヘッダー「my_project.H」を再度含めてみましょう。同じプロジェクトで、次のファイルを追加します。
//--------------------------------------
//Filename: "my_big_project_splitted.C"
#include "my_project.H"
void old_main_test(void){
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 5678;
int function_1(void) return 12;
int function_3(void) return 34;
注意すべき重要な機能:
ヘッダーファイルで関数が「静的」として定義されている場合、コンパイラ/リンカーは、そのインクルードファイルを使用する各モジュールでその名前の関数のインスタンスを見つける必要があります。
Cライブラリの一部である関数は、プロトタイプをそのモジュールでのみ「静的」に再定義することにより、1つのモジュールでのみ置き換えることができます。たとえば、「malloc」および「free」の呼び出しを置き換えて、メモリリーク検出機能を追加します。
指定子「extern」は関数には実際には必要ありません。「静的」が見つからない場合、関数は常に「外部」であると見なされます。
ただし、「extern」は変数のデフォルトではありません。通常、多くのモジュールで表示される変数を定義するヘッダーファイルでは、「extern」を使用する必要があります。唯一の例外は、ヘッダーファイルが1つだけのモジュールからインクルードされることが保証されている場合です。
多くのプロジェクトマネージャーは、このような変数をヘッダーファイル内ではなく、モジュールの先頭に配置する必要があります。ビデオゲームエミュレーター「Mame」などの一部の大規模プロジェクトでは、そのような変数は、それらを使用する最初の関数の上にのみ出現する必要があります。