ライブラリ ヘッダー ファイルには、関数の宣言のみが含まれます。では、ライブラリ関数を呼び出すと、関数はどのように正確に実行されるのでしょうか?
例: int strcmp ( const char * str1, const char * str2 );
C の strcmp 関数の宣言です。
プログラムで strcmp 関数を呼び出すとき、関数本体がヘッダー ファイルに存在しない場合、strcmp 関数はどのように正確に実行されるのでしょうか?
ライブラリ ヘッダー ファイルには、関数の宣言のみが含まれます。では、ライブラリ関数を呼び出すと、関数はどのように正確に実行されるのでしょうか?
例: int strcmp ( const char * str1, const char * str2 );
C の strcmp 関数の宣言です。
プログラムで strcmp 関数を呼び出すとき、関数本体がヘッダー ファイルに存在しない場合、strcmp 関数はどのように正確に実行されるのでしょうか?
ヘッダー ファイルには関数宣言のみが含まれます。これは、実装を気にせずに作業する必要があるコンテンツを公開するという主な目的の 1 つです。
実装の場所に関しては、ビルド時にランタイム ライブラリがプログラムに追加されるため、関数定義の「前方」宣言があるため、コーダーとしてこれらの関数をすべて呼び出すことができますが、そうではありません。実装がロードされる実行時まで。
その理由は、たとえば printf などの実装コードを、それを使用するすべてのプログラムにコピーするのはばかげているからです。これはかなりのメモリの無駄です。代わりに、宣言のみがプログラマーに公開され、OS は実行時にメモリ内の関数の実装を共有します。
strcmp がプログラムでどのように使用されるかを理解するには、たとえコンパイラーがその宣言しか見ていないとしても、リンクのプロセスを理解する必要があります。C プログラムのコンパイルは、次の 3 つの手順で構成されます。
3 番目のステップでは、いわゆるリンカ(通常はld
) が基本的に、リンクされたすべてのオブジェクト ファイルの内容を実行可能ファイルにダンプし、すべてのシンボルを解決します。シンボルとは、関数やグローバル変数など、グローバル名を持つものです。
プログラムがコンパイラによって生成されたオブジェクトファイルを呼び出すとき、strcmp
実際にはその関数の定義が含まれていません。むしろ、strcmp
後でリンカーによって解決されるシンボルへの参照だけがあります。リンカーは、すべてのオブジェクト ファイルとグローバル ライブラリを調べてから、これらの参照を解決します。
strcmp
はランタイムライブラリにあり、実行可能ファイルをビルドするとプログラムに追加されます。これがどのように機能するかの詳細は、オペレーティングシステムによって異なります。
この場合、他のユーザー定義ヘッダーと違いはありません。
string.h
対応するヘッダー ( for など) をインクルードしない場合strcmp
、コンパイラによって暗黙の宣言が行われます。
実行時に関数定義が見つからない(つまり、想定どおりにライブラリにない)場合、リンカは、デフォルトで行われる標準Cライブラリとリンクするときに文句を言います(たとえば-lc
、gccの場合の実行時) )。
使いたいコードprintf
は既にコンパイルされてどこかに保存されています。リンカーがオブジェクト コードを標準ライブラリにリンクすると、最終的な実行可能ファイルがビルドされます。
あなたが得るものを試しgcc -c somefile.c
てみてください。
また、オプションを試しgcc -v
て、それが与える出力を学びます。
コマンドが何をするかld
を調べれば、答えが得られます。
また、これはあなたに役立つと思います:コンパイル/リンク/関連についてのすべて
アップデート :
printf
また、すべてのプログラムを定義し、stdio.h
含めた場合を想像してくださいstdio.h
program.c :
#include <stdio.h> //suppose this contains definition of printf
int main()
{
/*Call printf() somewhere or maybe not */
}
gcc program.c -o 出力
したがって、ここにあるすべての定義はファイル内stdio.h
で置き換えられ、program.c
実行可能ファイルoutput
はかなり巨大になります。代わりに、頻繁に使用する関数を必要なときに 1 か所からprintf
呼び出す方がよいでしょう。stdio.h
コンパイルされたライブラリに存在します。一部のライブラリにリンクしているときにプロジェクトをコンパイルすると、コンパイル済みのライブラリが最終的なコンパイルに追加されます。