5

好吧,我认为我的问题有点有趣,我想了解我的 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,没有成功。

提前致谢!

卢卡斯。

4

1 回答 1

18

这里发生了两种不同的事情。

对于第一个示例,编译器不会生成对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当它看到对in的调用时useless.o,为时已晚。

于 2012-01-22T00:29:46.610 回答