【问题标题】:C Math sqrt and Gcc -lm option [duplicate]C Math sqrt 和 Gcc -lm 选项 [重复]
【发布时间】:2016-05-17 04:18:07
【问题描述】:

一些好的灵魂可以帮助我理解为什么我必须在案例 (1) 中使用 -lm gcc 选项(就像这样
gcc main.c -o main -lm) 而在案例 (2) 中没有?

案例(一)

#include <math.h>
int main() {
  float x = 4;
  sqrt(x);
  return 0;
}

案例(2)

#include <math.h>
int main() {
  sqrt(4);
  return 0;
}

我正在使用带有 gcc 的 Ubuntu 16.04。 我知道为什么我应该使用-lm,但我不知道为什么案例 (2) 没有它。

【问题讨论】:

  • 因为编译器知道sqrt(4) 是2。在第一种情况下,尝试gcc -O3 main.c -o main 看看是否有效。

标签: c gcc


【解决方案1】:

让我们来看看几个函数。这是第一个:

#include <math.h>

double func(double num) {
  return sqrt(num);
}

gcc -O3 -c so.c编译,用objdump -d so.o反汇编:

0000000000000000 <func>:
   0:   f2 0f 51 c8             sqrtsd %xmm0,%xmm1
   4:   66 0f 2e c9             ucomisd %xmm1,%xmm1
   8:   7a 05                   jp     f <func+0xf>
   a:   66 0f 28 c1             movapd %xmm1,%xmm0
   e:   c3                      retq   
   f:   48 83 ec 08             sub    $0x8,%rsp
  13:   e8 00 00 00 00          callq  18 <func+0x18>
  18:   48 83 c4 08             add    $0x8,%rsp
  1c:   c3                      retq   

所以我们有一堆 FPU 寄存器操作和一个调用。让我们尝试看看该调用调用了什么。运行nm so.o

0000000000000000 T func
                 U sqrt

所以我们定义(T)一个名为“func”的函数,并导入(U)一个名为sqrt的符号。最终的程序必须与-lm 链接,因为这是sqrt 实际定义的地方。

现在让我们尝试第二个功能:

#include <math.h>

double func() {
  return sqrt(4);
}

再次,使用gcc -O3 -c so.c 编译并使用objdump -d so.o 反汇编:

0000000000000000 <func>:
   0:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0        # 8 <func+0x8>
   7:   00 
   8:   c3                      retq   

没有 FPU 寄存器操作。没有函数调用。让我们通过nm so.o 进行验证:

0000000000000000 T func
0000000000000000 r .LC0

是的。不导入符号。

如果您省略#include &lt;math.h&gt;,您会得到这里发生了什么的提示:

$ gcc -O3 -g -c so.c
so.c: In function ‘func’:
so.c:2:10: warning: incompatible implicit declaration of built-in function ‘sqrt’
   return sqrt(4);
          ^

sqrt 是一个内置函数。编译器不会将其视为某种不透明的构造。它了解它的作用。在第二种情况下,编译器明白它不需要在运行时调用函数。它在编译期间知道答案是什么。它只是将答案放在返回寄存器中并称之为一天。由于运行时不包含对sqrt 的调用,因此无需与-lm 链接。

【讨论】:

  • 伙计,你太棒了! :) 非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
  • 2012-01-18
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
相关资源
最近更新 更多