好吧,我认为我的问题有点儿有趣,我想了解我的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
但没有成功。
提前致谢!
卢卡斯。
答案 0 :(得分:12)
这里有两件不同的事情。
对于第一个示例,编译器不会生成对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
的来电时,为时已晚。