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 编译器以来已经有一段时间了,如果这是一个糟糕的问题,请原谅我。

4

3 回答 3

6

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

# define M_LN10     2.30258509299404568402

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

于 2013-10-21T05:27:49.600 回答
6

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

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

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

于 2013-10-21T05:59:04.313 回答
2

由于某些原因,gcc 即使使用 -O0 也会优化 log(const)。所以在第一种情况下没有 log() 调用。检查装配以验证:

gcc 样本.c -S

例如,clang 不会在 O0 上对其进行优化。但是在 O2 gcc 优化了这两种情况下的调用。

于 2013-10-21T05:38:30.617 回答