链接错误 - gcc -lm

Luc*_*sBr 3 ubuntu linker gcc math.h ld

好吧,我认为我的问题有点有趣,我想了解我的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);
}
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是当我改变这个:

/*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);
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用相同的命令行编译,gcc响应:

/tmp/cctM0k56.o: In function `main':
ao_example3.c:(.text+0x29): undefined reference to `sin'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

然后停下来.怎么了?为什么我不能这样编译?

我也尝试了一次sudo ldconfig -v没有成功.

提前致谢!

卢卡斯.

Kei*_*son 12

这里有两件不同的事情.

对于第一个示例,编译器不会生成对的调用sin.它看到参数是一个常量表达式,因此它用sin(...)表达式的结果替换调用,并且不需要数学库.如果没有它,它也可以正常工作-lm.(但是你不应该指望它;当编译器执行这种优化时它并不总是显而易见的.)

(如果你用.编译

gcc -S useless.c
Run Code Online (Sandbox Code Playgroud)

并看一下useless.s,生成的汇编语言列表,你可以看到没有调用sin.)

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

gcc -o useless useless.c -lm
Run Code Online (Sandbox Code Playgroud)

要么

gcc useless.c -lm -o useless
Run Code Online (Sandbox Code Playgroud)

链接器按顺序处理文件,跟踪每个文件的未解析符号(sin,引用useless.o),然后在看到它们的定义时解析它们.如果放第-lm一个,则在处理数学库时没有未解析的符号; 当它看到来电sinuseless.o,已经太晚了.

  • 我正要发布相同的但不明白为什么第一个成功(也使用了`sin()`)。 (2认同)
  • 我已经重新排列了答案(它仍然具有相同的信息)。 (2认同)