首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么它不需要链接libm?

为什么它不需要链接libm?
EN

Stack Overflow用户
提问于 2013-04-25 00:25:19
回答 2查看 2.1K关注 0票数 5
代码语言:javascript
复制
#include <math.h>
#include <stdio.h>
int main()
{
   printf("%f", roundf(3.14));
}

我编译了上面的代码(没有使用-lm),添加使用ldd a.out,结果是

代码语言:javascript
复制
linux-vdso.so.1 =>  (0x00007fffab9ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd6da0f8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd6da4eb000)

为什么a.out没有链接到libm,但是可以使用圆形(或者类似sqrt之类的东西)?我使用nm测试libc.so.6和didn x86064.so.2,但所有这些都没有圆f的符号。

我想知道圆f是在哪里定义的,还是已经被编译器内联了?(与gcc 4.7.3和gcc 4.6.3进行测试)

答案是http://fedoraproject.org/w/index.php?title=UnderstandingDSOLinkChange

EN

回答 2

Stack Overflow用户

发布于 2013-04-25 00:29:28

作为优化,编译器将在编译时计算值并使用常量,因此不需要调用roundf()。您可以通过查看生成的代码来验证这一点:

代码语言:javascript
复制
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, %eax
    fldl    .LC1
    fstpl   4(%esp)
    movl    %eax, (%esp)
    call    printf
    leave
    ret

您可以看到在生成的程序集中没有调用roundf()。(您可以使用gcc -S filename.c生成该文件并读取生成的filename.s文件)。

票数 7
EN

Stack Overflow用户

发布于 2013-04-25 01:16:16

您在一条评论中提到了libstdc++,这让我怀疑问题在于您是在链接g++而不是gcc

gcc命令调用编译器和/或链接器。如果您使用它来编译源文件,它通常会决定语言(因此也决定要使用哪个编译器前端)。

g++命令类似,但它专门用于C++;如果它调用链接器,它会根据需要传递参数,以链接C++所需的libstdc++等库。

例如,这两个命令只编译而不链接:

代码语言:javascript
复制
gcc -c foo.cpp
g++ -c foo.cpp

(据我所知)是等价的,但以下命令:

代码语言:javascript
复制
gcc foo.cpp -o foo
g++ foo.cpp -o foo

不是;前者可能会失败(取决于foo.cpp使用的特性)。

结果发现,g++命令与gcc命令不同,它隐式地链接了数学库,至少在我的系统上的版本中是这样。因此,如果您的C++代码同时使用了特定于C++的特性(例如,<iostream>)和数学函数,那么将其与gcc命令链接可能会产生对libstdc++libm中定义的函数的抱怨--这正是您所看到的。

如果您链接到g++命令,这将解决问题。您可能需要修改您的Makefile或等效的,或者任何生成它的东西。

(如果这是解决方案,您可能应该在问题的标签列表中添加"c++“。)

至于你以前为什么没有遇到这个问题,我不知道。一些C(和/或C++)编译器将隐式地链接数学库;为其他编译器指定-lm的需要可以说是一个错误。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16204457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档