5

A1.c と A2.c の 2 つの .c ファイルがあります。

A1.c:

int i=0;
void main()
{}

A2.c:

int i=0;
void func()
{}

コンパイルはうまくいきますが、これら 2 つの .o ファイルをリンクしようとすると、「i の複数定義」エラーが発生します。ここではグローバル変数であることは理解していますが、他のファイルで使用するキーワードはi必要ありません。extern私のプロジェクトでは、extern. では、なぜエラーが発生するのでしょうか。

4

4 に答える 4

7

コンパイル時に、コンパイラは各グローバル シンボルをストロングまたはウィークとしてアセンブラにエクスポートし、アセンブラはこの情報を再配置可能オブジェクト ファイルのシンボル テーブルに暗黙的にエンコードします。関数と初期化されたグローバル変数は強いシンボルを取得します。初期化されていないグローバル変数は弱いシンボルを取得します。

この強いシンボルと弱いシンボルの概念を考慮して、Unix リンカは次の規則を使用して複数定義されたシンボルを処理します。

ルール 1:複数のストロング シンボルは許可されません。
ルール 2:強いシンボルと複数の弱いシンボルが与えられた場合、強いシンボルを選択します。
ルール 3:複数の弱いシンボルが与えられた場合、弱いシンボルのいずれかを選択します。

コード A1.c は次のとおりです。

int i=0; // Strong Symbol
void main() {}

A2.c:

int i=0; // Strong symbol
void func() {}

ルール 1により、これは許可されません。

詳細情報: http://www.geeksforgeeks.org/how-linkers-resolve-multiply-defined-global-symbols/

于 2015-01-05T22:50:27.173 に答える
3

C では、グローバル変数は、この他のコンパイル単位が存在することを認識している限り、それを宣言することによって、別のコンパイル単位からアクセスできますextern。リンカーは、extern 宣言と別の .c の定義をリンクするジョブを作成します。

コンパイルしている .c からのみ見えるようにする場合は、次のように指定する必要があります。static

static int i = 0;
于 2013-04-16T13:56:58.953 に答える
-1

もちろん、リンクでは失敗します。2 つの異なるメモリ位置にあるオブジェクトを参照する 2 つのオブジェクト ファイルを結合しようとします。

このような場合、変数の実際の定義はすべてのソース コードで UNIQUE でなければならず、この変数への他のすべての参照はexternalキーワードを使用して行う必要があります (先ほど説明したように)。

2 つのファイルの関係がわからないため、コンパイルは泣き言を言いません。リンカだけがそれを把握する必要があります。

于 2013-04-16T13:57:18.577 に答える