4

GCC 4.4.5がインストールされたgentoo Linuxを使用しています。gcc main.c -o mainを使用してエラーなしでそのようなプログラムをコンパイルおよびリンクでき、コマンド./mainは結果を正しく返します。

[main.c] 
#include <math.h>
#include <stdio.h>
int main(void)
{
    double c = ceil(2.5);
    printf("The ceil of 2.5 is %f\n", c);
    return 0;
}

しかし、ceilの呼び出しを別のソース ファイルに入れると、問題が発生します。

[calc.h]
#ifndef _CALC_H_
#define _CALC_H_
double myceil(double n);
#endif

[calc.c]
#include <math.h>
#include "calc.h"
double myceil(double n)
{
    return ceil(n);
}

[main1.c]
#include <stdio.h>
#include "calc.h"
int main(void)
{
    double c = myceil(2.5);
    printf("The ceil of 2.5 is %f\n", c);
    return 0;
}

コマンドgcc calc.c main1.c -o main1を使用すると、次のようなエラーが発生します。

/tmp/cc6GhJvZ.o: In function `myceil':
calc.c:(.text+0x19): undefined reference to `ceil'
collect2: ld returned 1 exit status

では、後者の場合に「未定義の参照」という厄介なエラーが発生したのはなぜですか? ライブラリ-lmを追加することでエラーを解消できることはわかっていますが、後者の場合に gcc がエラーをスローする理由を知りたいだけです。

4

3 に答える 3

5

私の推測では、GCC は定数に最適化さceil(2.5)れますが、はコンパイル時に不明なceil(n)ため定数ではなく、関数を参照する必要があります。これは、アセンブリの出力 ( ) を見ることで確認できます。ncalc.cgcc -S

更新:これは、x86 上の gcc 4.2.1 が最初の例に似たものを私に与えたものです:

.LC1:
    .string "%f\n"
    // [snip]
main:
    // [snip]
    fldl    .LC0
    fstpl   4(%esp)
    movl    $.LC1, (%esp)
    call    printf
    // [snip]
.LC0:
    .long   0
    .long   1074266112

ここでは、定数printfで呼び出されていることがわかります。double

次に、2番目の例と同様のことを行うと:

myceil:
    // [snip]
    fldl    -8(%ebp)
    fstpl   (%esp)
    call    ceil
    // [snip]

ここで、参照ceilされていることがわかります。

そうそう。あなたの呼び出しは、なしで機能する定数に最適化されていると思います-lm

于 2011-08-22T05:58:42.313 に答える
2

gcc には組み込み関数のリストがあり、そのceilうちの 1 つです。ceil私のOSXのバージョンでは、gccは両方のケースでビルトインを使用しているため-lm、必要ありません。ceilどうやらあなたの Gentoo コンパイラは異なる動作をし、場合によってはビルトインのみを使用します。でコンパイルしようとすると、両方のコンパイル-fno-builtinに使用する必要があります。-lm

于 2011-08-22T06:04:13.593 に答える
0

最初に main.c を main.o にコンパイルし、calc.c を calc.o にコンパイルしてから、それらをリンクすると機能しますか? これは通常、私が期待することです (単一のコマンド ラインで複数の C ファイルをコンパイルしようとするのではなく、オブジェクト ファイルをリンクします)。

于 2011-08-22T05:57:31.067 に答える