链接多个 C 源文件
我在 gentoo linux 上安装了 GCC 4.4.5。我可以使用 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 在后一种情况下会抛出错误。
I'm on gentoo linux with GCC 4.4.5 installed. I can compile and link such program without any errors using gcc main.c -o main, and the command ./main returns result correctly.
[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;
}
But when I put the invokation of ceil into another source file, the problem occurs.
[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;
}
Using the command gcc calc.c main1.c -o main1, such error occurs:
/tmp/cc6GhJvZ.o: In function `myceil':
calc.c:(.text+0x19): undefined reference to `ceil'
collect2: ld returned 1 exit status
So why did the annoying error "undefined references" happen in the latter case? And I know the error could be eliminated by adding an library -lm, however, I just want to know why gcc will throw the error in the latter case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的猜测是,GCC 将
ceil(2.5)
优化为常量,而ceil(n)
不是常量,因为编译时n
未知calc.c
,它需要引用该函数。您可以通过查看汇编输出 (gcc -S
) 来确认这一点。更新:这是 x86 上的 gcc 4.2.1 为我提供的与您的第一个示例类似的内容:
这里我们看到
printf
被使用double
调用持续的。现在,如果我执行与第二个示例类似的操作:
这里我们看到
ceil
被引用。所以是的。我想说,您的调用正在优化为无需
-lm
即可工作的常量。My guess is that GCC optimizes
ceil(2.5)
to a constant, whereasceil(n)
is not constant becausen
is not known when compilingcalc.c
, and it needs to reference the function. You can confirm this by looking at the assembly output (gcc -S
).Update: Here's what gcc 4.2.1 on x86 gave me for something similar to your first example:
Here we see
printf
being called with adouble
constant.Now if I do something similar to your second example:
Here we see
ceil
being referenced.So yeah. I'd say your call is being optimized to a constant in the one that works without
-lm
.gcc 有一个内置函数列表ceil 就是其中之一。在我的 OSX 版本上,gcc 在这两种情况下都使用内置的
ceil
,因此不需要-lm
。显然,您的 Gentoo 编译器的行为有所不同,并且在某些情况下仅使用内置的 ceil 。如果您尝试使用-fno-builtin
进行编译,则两次编译都必须使用-lm
。gcc has a list of built-in functions and
ceil
is one of them. On my version of OSX, gcc uses the built-inceil
in both of your cases so-lm
is not necessary. Apparently your Gentoo compiler behaves differently and only uses the built-inceil
in some cases. If you try compiling with-fno-builtin
then you'll have to use-lm
for both of your compilations.如果您首先将 main.c 编译为 main.o,将 calc.c 编译为 calc.o,然后链接它们,它会起作用吗?这通常是我所期望的(链接目标文件而不是尝试在单个命令行上编译多个 C 文件)。
Does it work if you first compile main.c to main.o and calc.c to calc.o, then link those? That's normally what I would expect (linking object files rather than trying to compile multiple C files on a single command line).