ここで 2 つの質問があります。
test.cライブラリ内のルーチンの宣言を提供するヘッダーなしでコンパイルするのはなぜですか?
test.cコマンド ラインの最初にリストされているとリンクが機能するのに、コマンド ラインtest.cの最後にリストされているとリンクが機能しないのはなぜですか?
ソースコードを示していないため、最初の質問に対して完全な回答を提供することはできません。他の人が指摘したように、C には、主に歴史的な理由から、暗黙の宣言を提供する余裕があります。これらの暗黙的な宣言は、ルーチンの実際の定義と一致しない可能性があり、エラーが発生する可能性があるため、暗黙的な宣言は避ける必要があります。
2番目の質問に対する答えはこれです。表示された 2 つのコマンド ラインのいずれかを指定すると、コンパイラはコンパイルしtest.cてリンカーを呼び出します。(コンパイラーは、リンクせずにコンパイルしたり、以前にコンパイルされたソースからオブジェクト・モジュールをリンクしたりするなど、他のことを行うようにすることもできます。)それらをリンカーに渡しました。特に、の-lcde前test.cに置くと、コンパイラは、リンカーを実行するときに、から-lcde来るオブジェクト モジュールの前に置きます。test.ctest.o
これは、リンカーの動作方法のために重要です。特に、リンカーには、定義が必要なシンボルのリストがあります。リストは最初は空です。リンカーは、コマンド ラインからの入力を左から右に処理します。リンカは、test.oコマンド ラインなどでオブジェクト モジュールを検出すると、オブジェクト モジュールを読み取り、処理します。多くの場合、オブジェクト モジュールには、ライブラリ ルーチンの呼び出しなど、定義されていないシンボルへの参照が含まれています。リンカーが以前のファイルからのこれらのシンボルの定義を既に持っている場合、参照を定義に接続します。定義がない場合は、リンカーが定義を必要とするシンボルのリストにシンボルを追加します。
リンカーは、ライブラリ ファイルを処理するときに、ライブラリ内の各オブジェクト モジュールをチェックして、そのオブジェクト モジュールがリンカーの必要な定義のリストにあるシンボルを定義しているかどうかを確認します。その場合、リンカーはそのオブジェクト モジュールを読み取り、それ (およびその定義) を、リンカーが構築している実行可能ファイルに追加します。そうでない場合、リンカーはそのオブジェクト モジュールを無視します。
test.c -lcdeこれで、機能するのに機能-lcde test.cしない理由がわかります。前者の場合、リンカはtest.o必要なものすべてのリストを作成し、cdeライブラリからそれらを取得します。後者の場合、リンカはcdeライブラリを認識しますが、まだそこから何も必要としないため、ライブラリから何も取得せずに続行します。次に、リンカーtest.cは必要なシンボルのリストを読み取り、追加します。次に、コマンド ラインが終了し、リンカにはファイルがなくなりますが、定義のないシンボルがまだ残っています。したがって、エラーが報告されます。
そのため、通常、ライブラリはコマンド ラインの最後にリストする必要があります。