好吧,我认为我的问题有点有趣,我想了解Ubuntu盒子中正在发生的事情。

我编译了以下无用的代码并将其与gcc -lm -o useless useless.c链接:

/*File useless.c*/
#include <stdio.h>
#include <math.h>
int main()
{
    int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * 440 * ((float) 1/44100)));
    return(0);
}

到现在为止还挺好。但是,当我更改为:
/*File useless.c*/
#include <stdio.h>
#include <math.h>
int main()
{
    int freq = 440;
    int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * freq * ((float) 1/44100)));
    return(0);
}

我尝试使用相同的命令行,gcc响应进行编译:
/tmp/cctM0k56.o: In function `main':
ao_example3.c:(.text+0x29): undefined reference to `sin'
collect2: ld returned 1 exit status

并停止。怎么了?为什么我不能那样编译?

我也尝试了sudo ldconfig -v,但没有成功。

提前致谢!

卢卡斯

最佳答案

这里有两种不同的情况。

对于第一个示例,编译器不会生成对sin的调用。可以看到该参数是一个常量表达式,因此它用表达式的结果替换了sin(...)调用,并且不需要数学库。如果没有-lm,它将同样有效。 (但是您不应该指望这一点;当编译器何时执行这种优化,何时不执行这种优化,并不总是很明显。)

(如果您使用

gcc -S useless.c

并查看生成的汇编语言列表useless.s,您可以看到没有对sin的调用。)

对于第二个示例,您确实需要-lm选项-但它必须在命令行的末尾,或者至少在需要它的文件(useless.c)之后:
gcc -o useless useless.c -lm

或者
gcc useless.c -lm -o useless

链接器按顺序处理文件,跟踪每个文件的未解析符号(sin,由useless.o引用),然后在看到其定义时对其进行解析。如果您首先将-lm放在首位,则在处理数学库时将没有未解析的符号;等到在sin中看到对useless.o的调用时,为时已晚。

关于gcc - 链接错误-gcc -lm,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8957967/

10-11 23:13