仅在更改输入参数时显示对sin的未定义引用

时间:2015-11-06 17:51:53

标签: c math compiler-errors sin

生命中第一次看到它。当输入参数改变时,编译器会给出函数未定义的错误。这怎么可能发生enter image description here

在图像中,对函数的第一次调用可以正常工作。如果我用变量删除s​​in函数调用,则此错误不存在。真的很好奇......

2 个答案:

答案 0 :(得分:3)

这就是原因。请考虑以下代码:

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

int main()
{
  printf("%.3f\n", sin(0.5));
  return 0;
}

GCC注意到你正在使用常数的正弦值并立即将其替换为sin(0.5)的实际值,正如您从下面主要的反汇编中看到的那样:

(gdb) disass main
Dump of assembler code for function main:
   0x000000000040052d <+0>: push   %rbp
   0x000000000040052e <+1>: mov    %rsp,%rbp
   0x0000000000400531 <+4>: sub    $0x10,%rsp
   0x0000000000400535 <+8>: movabs $0x3fdeaee8744b05f0,%rax
   0x000000000040053f <+18>:    mov    %rax,-0x8(%rbp)
   0x0000000000400543 <+22>:    movsd  -0x8(%rbp),%xmm0
   0x0000000000400548 <+27>:    mov    $0x4005e4,%edi
   0x000000000040054d <+32>:    mov    $0x1,%eax
   0x0000000000400552 <+37>:    callq  0x400410 <printf@plt>
   0x0000000000400557 <+42>:    mov    $0x0,%eax
   0x000000000040055c <+47>:    leaveq 
   0x000000000040055d <+48>:    retq   
End of assembler dump.

现在让我们对其进行更改,以便无法进行优化:

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

int main(int argc, char** argv)
{
  printf("%.3f\n", sin((double)argc));
  return 0;
}

现在你实际上需要调用数学库中定义的sin()函数。如果你没有在选项的正确位置向gcc提供-lm标志,那么链接就会失败(最好的位置在最后)。这是反汇编:

Dump of assembler code for function main:
   0x000000000040063d <+0>: push   %rbp
   0x000000000040063e <+1>: mov    %rsp,%rbp
   0x0000000000400641 <+4>: sub    $0x20,%rsp
   0x0000000000400645 <+8>: mov    %edi,-0x4(%rbp)
   0x0000000000400648 <+11>:    mov    %rsi,-0x10(%rbp)
   0x000000000040064c <+15>:    cvtsi2sdl -0x4(%rbp),%xmm0
   0x0000000000400651 <+20>:    callq  0x400540 <sin@plt>
   0x0000000000400656 <+25>:    movsd  %xmm0,-0x18(%rbp)
   0x000000000040065b <+30>:    mov    -0x18(%rbp),%rax
   0x000000000040065f <+34>:    mov    %rax,-0x18(%rbp)
   0x0000000000400663 <+38>:    movsd  -0x18(%rbp),%xmm0
   0x0000000000400668 <+43>:    mov    $0x400704,%edi
   0x000000000040066d <+48>:    mov    $0x1,%eax
   0x0000000000400672 <+53>:    callq  0x400510 <printf@plt>
   0x0000000000400677 <+58>:    mov    $0x0,%eax
   0x000000000040067c <+63>:    leaveq 
   0x000000000040067d <+64>:    retq   
End of assembler dump.

请注意对sin @ plt。

的调用

从你的截图中看起来你正在使用gcc周围的某种可视化工具。检查其上的文档如何更改链接库。如果它允许你直接修改链接器命令,只需将-lm放在它的末尾,你的代码就可以工作。

答案 1 :(得分:0)

这只是猜想。如果您使用数学库并且只在顶部添加标题,则错误是因为您没有链接到库。 maths.h应该适合你。