好吧,我觉得我的问题有点有趣,我想了解我的 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
放在前面,它在处理数学库时就没有未解析的符号;当它在 useless.o
中看到对 sin
的调用时,已经太晚了。
关于gcc - 与 'gcc' 和 '-lm' 相关的链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8957967/