链接多个C源文件

时间:2011-08-22 05:51:45

标签: c linker gentoo gcc4

我在安装了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会在后一种情况下抛出错误。

3 个答案:

答案 0 :(得分:5)

我的猜测是GCC将ceil(2.5)优化为常量,而ceil(n)不是常量,因为编译ncalc.c未知,并且需要引用gcc -S功能。您可以通过查看汇编输出(.LC1: .string "%f\n" // [snip] main: // [snip] fldl .LC0 fstpl 4(%esp) movl $.LC1, (%esp) call printf // [snip] .LC0: .long 0 .long 1074266112 )确认这一点。

更新:以下是x86上的gcc 4.2.1给出了类似于你的第一个例子的内容:

printf

我们在此处看到doublemyceil: // [snip] fldl -8(%ebp) fstpl (%esp) call ceil // [snip] 常量调用。

现在,如果我做了类似于你的第二个例子的事情:

ceil

我们在此处看到-lm被引用。

所以是的。我会说你的电话被优化为一个在没有{{1}}的情况下工作的常量。

答案 1 :(得分:2)

gcc列有built-in functionsceil就是其中之一。在我的OSX版本中,gcc在两种情况下都使用内置ceil,因此不需要-lm。显然,您的Gentoo编译器的行为有所不同,在某些情况下仅使用内置的ceil。如果您尝试使用-fno-builtin进行编译,那么您必须使用-lm进行两次编辑。

答案 2 :(得分:0)

如果你首先将main.c编译为main.o并将calc.c编译为calc.o,然后将它们链接起来,它是否有用?这通常是我所期望的(链接目标文件而不是尝试在单个命令行上编译多个C文件)。