【问题标题】:Why is -lm not necessary in some cases when compiling and linking C code?为什么在编译和链接 C 代码时在某些情况下不需要 -lm?
【发布时间】:2013-10-29 11:39:32
【问题描述】:

我这里有一个示例文件:

#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 编译器了,如果这是一个糟糕的问题,请原谅我。

【问题讨论】:

    标签: c gcc macros compiler-optimization math.h


    【解决方案1】:

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

    # define M_LN10     2.30258509299404568402
    

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

    【讨论】:

      【解决方案2】:

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

      gcc sample.c -S

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-27
          • 2016-06-21
          • 1970-01-01
          • 1970-01-01
          • 2012-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多