Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C数学sqrt和Gcc-lm选项_C_Gcc - Fatal编程技术网

C数学sqrt和Gcc-lm选项

C数学sqrt和Gcc-lm选项,c,gcc,C,Gcc,一些善良的灵魂能帮助我理解为什么我必须使用-lmgcc选项(像这样 gcc main.c-o main-lm)在第(1)种情况下,而在第(2)种情况下没有 案例(1) #包括 int main(){ 浮动x=4; sqrt(x); 返回0; } 案例(2) #包括 int main(){ sqrt(4); 返回0; } 我正在使用Ubuntu 16.04和gcc。 我知道为什么我应该使用-lm,但我不知道没有它为什么案例(2)可以工作。让我们看看几个函数。这是第一个: #include &l

一些善良的灵魂能帮助我理解为什么我必须使用
-lm
gcc选项(像这样
gcc main.c-o main-lm
)在第(1)种情况下,而在第(2)种情况下没有

案例(1)

#包括
int main(){
浮动x=4;
sqrt(x);
返回0;
}
案例(2)

#包括
int main(){
sqrt(4);
返回0;
}
我正在使用Ubuntu 16.04和gcc。
我知道为什么我应该使用
-lm
,但我不知道没有它为什么案例(2)可以工作。

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

#include <math.h>

double func(double num) {
  return sqrt(num);
}
所以我们有一堆FPU寄存器操作和一个调用。让我们试着看看那叫什么。运行
nm 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   
0000000000000000 T func
                 U sqrt
0000000000000000 <func>:
   0:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0        # 8 <func+0x8>
   7:   00 
   8:   c3                      retq   
0000000000000000 T func
0000000000000000 r .LC0
因此,我们正在定义(
T
)一个名为“func”的函数,并导入(
U
)一个名为
sqrt
的符号。最终的程序必须与
-lm
链接,因为
sqrt
实际上就是在这里定义的

现在,让我们尝试第二个函数:

#include <math.h>

double func() {
  return sqrt(4);
}
没有FPU寄存器操作。没有函数调用。让我们用
nmso.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   
0000000000000000 T func
                 U sqrt
0000000000000000 <func>:
   0:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0        # 8 <func+0x8>
   7:   00 
   8:   c3                      retq   
0000000000000000 T func
0000000000000000 r .LC0
是的。不导入符号

如果省略
#include
,您会得到这里发生的事情的提示:


sqrt
是一个内置函数。编译器不会将其视为某种不透明的构造。它知道自己在做什么。在第二种情况下,编译器知道它不需要在运行时调用函数。在编译过程中,它知道答案是什么。它只需将答案放在报税表中,并称之为一天。由于运行时不包含对
sqrt
的调用,因此不需要与
-lm

链接,因为编译器知道
sqrt(4)
是2。在第一种情况下,尝试一下gcc-O3 main.c-o main,看看它是否有效非常感谢你!