私は2つのモジュール(.cファイル)と1つの.hヘッダファイルを持っています:
file1.c:
#include
#include "global.h"
int main()
{
i = 100;
printf("%dn",i);
foo();
return 0;
}
file2.c
#include
#include "global.h"
void foo()
{
i = 10;
printf("%dn",i);
}
global.h
int i;
extern void foo()
gcc file1.c
file2.cを実行するとすべて正常に動作し、期待される出力が得られます。今、私は0と言うようにヘッダーファイル内の変数
‘i’を初期化し、再度コンパイルするとリンカーエラーが発生します:
/tmp/cc0oj7yA.o:(.bss+0x0): multiple definition of `i'
/tmp/cckd7TTI.o:(.bss+0x0): first defined here
ヘッダーファイル(gcc
file1.c)の初期化でfile1.c(foo()への呼び出しを削除する)をコンパイルするだけで、すべて正常に動作します。何が起こっている?
ベストアンサー
以下の3つのシナリオがあります。
- 2つの
.c
ファイルと int i;
2つの.c
ファイルと int i = 100;
のヘッダー(またはそれ以外の値) 1.c
ファイルと int i = 100;
それぞれのシナリオで、ヘッダファイルの内容を .c
ファイルと .o
ファイルにコンパイルしたこの .c
これらは一緒につながっています。
次に、
- すべての
-
は機能しません。
.o
ファイル内のすべてのファイル名を指定します。 -
.o
ファイルが1つしかなく、衝突の可能性がないので、もちろん動作します。
.o
ファイルにはそのうちの1つが含まれているので、リンカーは「ok」と言います。両方の.o
ファイルには(たとえ値が同じであっても)衝突する値を持つ定義が含まれているため、
きれいなことがIMHOになる
- ヘッダーファイルに
extern int i;
またはint
i; - 次に、
file1.c
にiの “実際の”定義(つまりint i =
)を置きます。この場合、この初期化はプログラムの開始時に使用され、
100;
main()
の対応する行は省略できます。
(また、命名は単なる例であり、実際のプログラムではグローバル変数の名前をi
にしないでください)。