9

外部リンケージがあるかのように main を宣言する必要があるのはなぜですか?

なぜ静的であってはならないのですか?

外部リンケージとはどういう意味ですか??

4

2 に答える 2

29

起動ファイルをプログラムにリンクするためです。このプログラムには、(通常は) メインを呼び出すアセンブラー コードが含まれています。メインが静的である場合、そのコードはメインを呼び出すことができません。

external linkage他のいわゆるtranslation-unitsは、独自の翻訳単位で extern 宣言されたシンボルを見ることができることを意味します。したがって、メインは extern であり、そのアドレスを示す変換単位シンボル テーブルにエントリがあります。他の変換単位は、main を呼び出したいときにそのアドレスにジャンプできます。

static linkageは、シンボルが厳密に翻訳単位ローカルであることを意味します。これは、他の人translation unitsがそのシンボルを見ることができないことを意味します。したがって、静的リンケージを持つシンボルは、異なる翻訳単位で複数回発生する可能性があり、ローカルであるため互いに衝突することはありません。

編集:一般に、翻訳単位からコンパイラによって生成されたファイルは、その特定のコンパイラに固有です。Linux 上の gcc では、多くの場合、ELF オブジェクト形式が使用されます。以下を使用してシンボル テーブルを表示できますreadelf -sW <file>.o(以下の簡単なテスト ファイル)。

test.c

void bar(void);

static int foo(void) {
    return 1;
}

int main(void) {
    bar();
    return foo();
}

readelf の出力は次のとおりです。

Symbol table '.symtab' contains 10 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS test.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    3
     4: 00000000     0 SECTION LOCAL  DEFAULT    4
     5: 00000000    10 FUNC    LOCAL  DEFAULT    1 foo
     6: 00000000     0 SECTION LOCAL  DEFAULT    6
     7: 00000000     0 SECTION LOCAL  DEFAULT    5
     8: 0000000a    36 FUNC    GLOBAL DEFAULT    1 main
     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND bar

main 関数と、main によって呼び出される static foo 関数が表示されます。また、ファイルで定義されていないが、別のオブジェクトファイルで定義されている関数が呼び出されています。オブジェクト ファイルがまだ最終的にリンクされていないため、関数にはまだ最終的なアドレスが割り当てられていません。最後のリンクの後、これらは実行可能ファイルに配置され、アドレスが割り当てられます。オブジェクト ファイルには、まだ定義されていない関数への呼び出しのエントリが含まれているため、ファイルがリンクされると、それらの呼び出し命令に最終的なアドレスが格納されます ( readelf -r <file>.o)。

Relocation section '.rel.text' at offset 0x308 contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000001c  00000902 R_386_PC32        00000000   bar
于 2008-11-26T11:56:17.767 に答える
9

コードの実際の開始点は、C ランタイム ライブラリに埋もれています。このランタイム ライブラリは、main() ルーチンを呼び出します。リンカが C RTL 呼び出しを main() 関数に接続するためには、ファイルの外部で可視である必要があります。

外部リンケージはまさにこれです: 問題の名前がオブジェクト ファイルのエクスポートの一部として表示されることを意味します。リンカの仕事は、未処理のインポートがないように、すべてのインポートとエクスポートを結合することです。

于 2008-11-26T11:57:02.290 に答える