当仅更改其输入参数时显示对 sin 的未定义引用
Showing undefined reference to sin when only the input parameter to it is changed
人生第一次见。当更改输入参数时,编译器会给出函数未定义的错误。怎么会这样
在图片中,第一次调用该函数时没有错误。如果我删除带有变量的 sin 函数调用,则不会出现此错误。非常好奇.....
这只是推测。如果您使用数学库并且只在顶部添加 header,则错误是因为您没有使用该库 link。 maths.h 应该适合你。
原因如下。考虑这段代码:
#include <stdio.h>
#include <math.h>
int main()
{
printf("%.3f\n", sin(0.5));
return 0;
}
GCC 注意到您正在取常数的正弦值并立即将其替换为 sin(0.5) 的实际值,正如您从下面的 main 反汇编中看到的那样:
(gdb) disass main
Dump of assembler code for function main:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub [=11=]x10,%rsp
0x0000000000400535 <+8>: movabs [=11=]x3fdeaee8744b05f0,%rax
0x000000000040053f <+18>: mov %rax,-0x8(%rbp)
0x0000000000400543 <+22>: movsd -0x8(%rbp),%xmm0
0x0000000000400548 <+27>: mov [=11=]x4005e4,%edi
0x000000000040054d <+32>: mov [=11=]x1,%eax
0x0000000000400552 <+37>: callq 0x400410 <printf@plt>
0x0000000000400557 <+42>: mov [=11=]x0,%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 [=13=]x20,%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 [=13=]x400704,%edi
0x000000000040066d <+48>: mov [=13=]x1,%eax
0x0000000000400672 <+53>: callq 0x400510 <printf@plt>
0x0000000000400677 <+58>: mov [=13=]x0,%eax
0x000000000040067c <+63>: leaveq
0x000000000040067d <+64>: retq
End of assembler dump.
注意对 sin@plt 的调用。
从您的屏幕截图看来,您正在使用某种围绕 gcc 的可视化工具。查看有关如何更改链接器库的文档。如果它会让您直接修改链接器命令,只需将 -lm 放在它的末尾,您的代码应该可以工作。
人生第一次见。当更改输入参数时,编译器会给出函数未定义的错误。怎么会这样
在图片中,第一次调用该函数时没有错误。如果我删除带有变量的 sin 函数调用,则不会出现此错误。非常好奇.....
这只是推测。如果您使用数学库并且只在顶部添加 header,则错误是因为您没有使用该库 link。 maths.h 应该适合你。
原因如下。考虑这段代码:
#include <stdio.h>
#include <math.h>
int main()
{
printf("%.3f\n", sin(0.5));
return 0;
}
GCC 注意到您正在取常数的正弦值并立即将其替换为 sin(0.5) 的实际值,正如您从下面的 main 反汇编中看到的那样:
(gdb) disass main
Dump of assembler code for function main:
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub [=11=]x10,%rsp
0x0000000000400535 <+8>: movabs [=11=]x3fdeaee8744b05f0,%rax
0x000000000040053f <+18>: mov %rax,-0x8(%rbp)
0x0000000000400543 <+22>: movsd -0x8(%rbp),%xmm0
0x0000000000400548 <+27>: mov [=11=]x4005e4,%edi
0x000000000040054d <+32>: mov [=11=]x1,%eax
0x0000000000400552 <+37>: callq 0x400410 <printf@plt>
0x0000000000400557 <+42>: mov [=11=]x0,%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 [=13=]x20,%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 [=13=]x400704,%edi
0x000000000040066d <+48>: mov [=13=]x1,%eax
0x0000000000400672 <+53>: callq 0x400510 <printf@plt>
0x0000000000400677 <+58>: mov [=13=]x0,%eax
0x000000000040067c <+63>: leaveq
0x000000000040067d <+64>: retq
End of assembler dump.
注意对 sin@plt 的调用。
从您的屏幕截图看来,您正在使用某种围绕 gcc 的可视化工具。查看有关如何更改链接器库的文档。如果它会让您直接修改链接器命令,只需将 -lm 放在它的末尾,您的代码应该可以工作。