3

私はGCCに関する本を読んでいました。デフォルトでは、標準ライブラリのみがCプログラムにリンクされているとのことです。pow()は標準ライブラリにないため、フラグを使用してリンクする必要があります-lm。ただし、コンパイルしたときは、次のように単純に使用しました。

gcc hello.c -o hello

そしてそれはまだ働いた..

また、同様の問題がもう 1 つあります。この本ではprintf("%f\n", 4);、C プログラムに があり、オプションなしでコンパイルした-Wall場合、警告は発行されないとも述べています。ただし、オプションなしでコンパイルしようとしました-Wallが、それでも警告が表示されました。

hello.c:6:2: 警告: フォーマット '%f' はタイプ 'double' の引数を想定していますが、引数 2 のタイプは 'int' です [-Wformat]

どうしてこれなの?この本には、プログラムをコンパイルして警告を表示するには、提供する必要がある-lmと書かれてい-Wallましたが、どちらも使用しませんでしたが、プログラムをコンパイルして警告を受け取りましたか?

ありがとうございました!

4

2 に答える 2

7

いくつかの実験に基づくもう少しの情報。

このプログラムを考えてみましょう:

#include <stdio.h>
#include <math.h>
int main(void) {
#ifdef CONSTANT
    double x = pow(2.0, 10.0);
#else
    double expon = 10.0;
    double x = pow(2.0, expon);
#endif
    printf("x = %f\n", x);
    return 0;
}

Ubuntuでは、コンパイルすると

$ gcc c.c -o c

への未定義の参照について文句を言いpowます。追加-lmすると修正されます。

でもこれは:

$ gcc -DCONSTANT c.c -o c

pow()呼び出しを定数に置き換えて、エラーなしでコンパイルおよびリンクします1024.0。でもこれは:

$ gcc -fno-builtin -DCONSTANT c.c -o c

への未定義の参照について再び文句を言いpowます。

結論: gcc は、powコンパイル時に結果を判別できる場合にのみ の組み込み実装を使用します。それ以外の場合は、関数への明示的な呼び出しが生成されます。これには とのpow()リンクが必要-lmです。

また、これは C ライブラリの編成方法に依存することにも注意してください (ライブラリは個別に提供されます。gcc の一部ではありません)。Ubuntu で使用されるglibcではなくnewlibを使用する Cygwinでは、このオプションは必要ありません。どうやら、数学ルーチンは個別に提供されるのではなく、標準ライブラリの不可欠な部分です。(Cygwin の gcc は引き続きオプションを受け入れます。)-lm-lm

于 2012-07-08T06:11:52.873 に答える
5

GCC は、いくつかの標準ライブラリ関数をビルトインとして提供しています。

GCC には、上記以外にも多数の組み込み関数が用意されています。これらのいくつかは、例外または可変長引数リストの処理で内部的に使用するためのものであり、時々変更される可能性があるため、ここでは説明しません。これらの機能を一般的に使用することはお勧めしません。

残りの関数は、最適化のために提供されています。

ビルトインのリストを見ると、それpowがその 1 つであることがわかります。

コンパイラ オプションを追加-fno-builtinすると、期待どおりのリンカー エラーが発生するはずです。

于 2012-07-08T04:59:19.747 に答える