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

use*_*999 9 c macros gcc math.h compiler-optimization

我这里有一个示例文件:

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

int main(){
  printf("%f\n", log(10));
}
Run Code Online (Sandbox Code Playgroud)

当我用gcc sample.c -o a它编译它时工作得很好.我可以运行它./a并产生2.302585预期的输出.

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

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

int main(){
  double a = 10;
  printf("%f\n", log(a));
}
Run Code Online (Sandbox Code Playgroud)

它没有编译gcc sample.c -o a.相反,我必须使用,gcc sample.c -o a -lm以便我可以明显地告诉它"链接数学"...这是我没有真正遵循的地方,为什么我不必在第一个例子中链接数学?它究竟是什么意思必须"链接数学"?自从我使用C编译器以来已经有一段时间了,所以如果这是一个糟糕的问题,请原谅我.

Cro*_*man 6

检查反汇编,您可能会发现编译器log()在第一种情况下完全优化了调用(因此无需链接),但在第二种情况下则没有.在这种特殊情况下,glibc定义:

# define M_LN10     2.30258509299404568402
Run Code Online (Sandbox Code Playgroud)

math.h,例如,任何标准库函数可以被实现为宏,因此它可以计算出其中的一些东西没有一个函数调用.


Yu *_*Hao 6

根据GCC文档,可能不会调用数学库函数,某些内联函数已定义,在某些情况下可能会被调用.

... GNU C库为许多常用的数学函数提供了优化.当使用GNU CC并且用户激活优化器时,会定义几个新的内联函数和宏.这些新函数和宏与库函数具有相同的名称,因此使用它们而不是后者.在内联函数的情况下,编译器将决定使用它们是否合理,并且此决定通常是正确的.

这意味着不需要调用库函数,并且可以显着提高生成代码的速度.缺点是代码大小会增加,并且增加并不总是可以忽略不计.