在编译和链接C代码时,为什么有些情况下不需要使用-lm?

9
我这里有一个示例文件:

我这里有一个示例文件:

#include <stdio.h>
#include <math.h>

int main(){
  printf("%f\n", log(10));
}

当我用gcc sample.c -o a编译代码时就能正常运行,通过./a可以得到预期的输出值2.302585

然而,当我的文件看起来像这样:

#include <stdio.h>
#include <math.h>

int main(){
  double a = 10;
  printf("%f\n", log(a));
}

使用gcc sample.c -o a编译代码会出错,需要使用gcc sample.c -o a -lm命令才能成功编译,似乎要告诉它“链接数学库”...我不是很明白,在第一个示例中为什么不需要链接数学库?链接数学库到底意味着什么?既然已经有一段时间没有使用C编译器了,所以如果这个问题问的不好,请原谅。

3个回答

7
根据GCC文档,可能无法调用数学库函数,某些内联函数在特定情况下定义并可能被调用。
GNU C库为许多经常使用的数学函数提供了优化。当使用GNU CC并激活优化器时,将定义几个新的内联函数和宏。这些新函数和宏具有与库函数相同的名称,因此将使用它们代替后者。对于内联函数,编译器将决定是否合理使用它们,该决策通常是正确的。
这意味着可能不需要调用库函数,可以显著提高生成代码的速度。缺点是代码大小会增加,而且增加量并非总是可以忽略不计的。

6

检查反汇编代码,你很可能会发现编译器在第一种情况下完全优化了对 log() 的调用(因此没有任何需要链接的东西),但在第二种情况下没有。在这种特定情况下,glibc 定义:

# define M_LN10     2.30258509299404568402

例如,在math.h中,任何标准库函数都可以实现为宏,因此它可以在不进行函数调用的情况下计算其中一些内容。


2
由于某些原因,即使使用-O0,gcc也会优化log(const)。因此,在第一种情况下没有log()调用。检查汇编代码以验证:
gcc sample.c -S
例如,clang在O0上不会将其优化掉。但是,在O2上,gcc会优化两种情况的调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接