简体   繁体   English

链接多个C源文件

[英]Linking multiple C source files

I'm on gentoo linux with GCC 4.4.5 installed. 我在安装了GCC 4.4.5的gentoo linux上。 I can compile and link such program without any errors using gcc main.c -o main , and the command ./main returns result correctly. 我可以使用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;
}

But when I put the invokation of ceil into another source file, the problem occurs. 但是,当我将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;
}

Using the command gcc calc.c main1.c -o main1 , such error occurs: 使用命令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

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. 我知道可以通过添加库-lm来消除错误,但是,我只是想知道为什么gcc会在后一种情况下抛出错误。

My guess is that GCC optimizes ceil(2.5) to a constant, whereas ceil(n) is not constant because n is not known when compiling calc.c , and it needs to reference the function. 我的猜测是GCC将ceil(2.5)优化为常数,而ceil(n)不是常数,因为在编译calc.c时不知道n ,并且它需要引用该函数。 You can confirm this by looking at the assembly output ( gcc -S ). 您可以通过查看装配输出( gcc -S )来确认这一点。

Update: Here's what gcc 4.2.1 on x86 gave me for something similar to your first example: 更新:这是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

Here we see printf being called with a double constant. 这里我们看到用double常量调用printf

Now if I do something similar to your second example: 现在,如果我做了类似于你的第二个例子:

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

Here we see ceil being referenced. 在这里,我们看到ceil被引用。

So yeah. 是的。 I'd say your call is being optimized to a constant in the one that works without -lm . 我会说你的调用被优化为一个不带-lm的常量。

gcc has a list of built-in functions and ceil is one of them. gcc有一个内置函数列表, ceil就是其中之一。 On my version of OSX, gcc uses the built-in ceil in both of your cases so -lm is not necessary. 在我的OSX版本中,gcc在两种情况下都使用内置ceil ,因此不需要-lm Apparently your Gentoo compiler behaves differently and only uses the built-in ceil in some cases. 显然,你的Gentoo编译器的行为有所不同,在某些情况下只使用内置的ceil If you try compiling with -fno-builtin then you'll have to use -lm for both of your compilations. 如果您尝试使用-fno-builtin进行编译,则必须使用-lm进行两次编译。

Does it work if you first compile main.c to main.o and calc.c to calc.o, then link those? 如果你首先将main.c编译为main.o并将calc.c编译为calc.o,然后链接它们,它是否有效? That's normally what I would expect (linking object files rather than trying to compile multiple C files on a single command line). 这通常是我所期望的(链接目标文件而不是尝试在单个命令行上编译多个C文件)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM