次のコードがあります (この質問のために最低限の基本まで削ぎ落とされています)。
#include<stdio.h>
#include<math.h>
double f1(double x)
{
double res = sin(x);
return 0;
}
/* The main function */
int main(void)
{
return 0;
}
コンパイルするとgcc test.c
次のエラーが発生しますが、その理由がわかりません。
/tmp/ccOF5bis.o: In function `f1':
test2.c:(.text+0x13): undefined reference to `sin'
collect2: ld returned 1 exit status
sin
しかし、関数内から呼び出すさまざまなテスト プログラムを作成しましたmain
が、それらは完璧に動作します。ここでは明らかに何か間違ったことをしているに違いありませんが、それは何でしょうか?
ベストアンサー1
正しい math.h ヘッダー ファイルへの参照を使用してコードをコンパイルしましたが、リンクしようとしたときに、数学ライブラリを含めるオプションを忘れました。その結果、.o オブジェクト ファイルはコンパイルできますが、実行可能ファイルをビルドすることはできません。
Paul がすでに述べたように、-lm
実行可能ファイルを生成しようとしている手順で数学ライブラリにリンクするには、「 」を追加します。
なぜ for
sin()
in ではオプションを明示的に<math.h>
必要としないのに、 for in ではオプションを明示的に必要としないのでしょうか?-lm
printf()
<stdio.h>
これらの関数は両方とも「Single UNIX 仕様」の一部として実装されているためです。この標準の歴史は興味深く、さまざまな名前で知られています (IEEE Std 1003.1、X/Open Portability Guide、POSIX、Spec 1170)。
この基準は、「標準 C ライブラリ」ルーチンを「標準 C 数学ライブラリ」ルーチンから明確に分離します (277 ページ)関連する文章を以下に転載します。
標準Cライブラリ
外部参照を解決するために、標準 C ライブラリが自動的に検索されます
cc
。このライブラリは、第 1 巻で定義されているように、数学ルーチンを除く基本システムのすべてのインターフェイスをサポートします。標準 C 数学ライブラリ
このライブラリは、第 1 巻で定義されている基本システム数学ルーチンをサポートします。オプション
cc
は-lm
、このライブラリを検索するために使用されます。
この分離の理由は、いくつかの要因によって影響を受けました。
- のUNIX戦争AT&T のオリジナルの UNIX 製品からの乖離が拡大しました。
- UNIX プラットフォームの数が増えたことにより、オペレーティング システム用のソフトウェアの開発が困難になりました。
- ソフトウェア開発者にとっての最低共通基準を定義する試みが開始されました。1988 POSIXと呼ばれる。
- ソフトウェア開発者は、より多くのプラットフォームに到達するために、POSIX 標準に準じてプログラミングし、「POSIX 準拠システム」でソフトウェアを提供します。
- UNIX の顧客は、ソフトウェアを実行するために「POSIX 準拠」の UNIX システムを要求しました。
別のライブラリを導入するという決定につながったプレッシャーには、-lm
おそらく次のようなものが含まれますが、これらに限定されるわけではありません。
- 多くのアプリケーションは数学ライブラリに埋め込まれた関数を使用しないため、これは libc のサイズを小さく保つための良い方法のようです。
- これにより、数学ライブラリの実装に柔軟性がもたらされ、一部の数学ライブラリはより大きな埋め込みルックアップ テーブルに依存し、他の数学ライブラリはより小さなルックアップ テーブル (コンピューティング ソリューション) に依存する場合があります。
- 本当にサイズに制約のあるアプリケーションの場合、数学ライブラリを非標準的な方法(単に取り出して
sin()
カスタムビルドのライブラリに配置するなど)で再実装できます。
いずれにせよ、C 言語の一部として自動的に含まれないことが標準の一部になったため、 を追加する必要があります-lm
。