只编译x86_一个有趣却容易忽略的编译链接问题

作者:守望先生

来源:编程珠玑

你知道,为什么在C++中使用了pow函数不需要链接libm库吗?

什么情况需要指定链接库?

在解释之前,先回顾一下。

//来源:公众号【编程珠玑】
//https://www.yanbinghu.com
#include
#include
int main(void){
    int b = 2;
    double a = pow(b,b);
    printf("%f\n",a);
    return 0;
}

代码本身比较简单,pow(x,y)用于计算x的y次幂。

这里由于pow函数并不在lib库中,默认情况下,编译的时候只链接了libc库,因此如果不指定链接库,则会报错:

$ gcc -o test test.c
/tmp/ccKDgtzz.o: In function `main':
test.c:(.text+0x22): undefined reference to `pow'
collect2: error: ld returned 1 exit status

从报错信息来看,我们知道是找不到pow函数的定义。

通过man手册也可以查看到,编译是需要包含头文件math.h和链接数学库的:

$ man pow
       #include 

       double pow(double x, double y);
       float powf(float x, float y);
       long double powl(long double x, long double y);

       Link with -lm.

即像下面这样是可以的:

$ gcc -o test test.c -lm
$ ./test
4.000000

gcc在编译的时候默认链接的是libc库,其他库需要手动指定。

但是,看下面的代码:

//来源:公众号【编程珠玑】
//作者:守望先生
#include
#include
int main(){
    int b = 2;
    double a = pow(b,b);
    std::cout<std::endl;return 0;
}

编译运行:

$ g++ -o test test.cpp
$ ./test
4

我们并没有手动指定链接库,但是却可以编译过!

那么,问题来了!

为何在C++中使用pow函数不需要手动指定链接数学库libm,而C里面却需要呢?

为了解答这个问题,我们必须知道C++的程序中,到底有没有链接libm库。如何查看呢?还记得在《linux常用命令-开发调试篇》中提到的ldd吗?它可以查看当前程序链接了哪些动态库:

$ ldd test
    linux-vdso.so.1 =>  (0x00007ffd41bda000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6230cca000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f62309c1000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f62305f7000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f623104c000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f62303e1000)

看到没有,除了链接了最基本的libstdc++库,还链接了libc和libm库!也就是说,虽然没有手动指定链接,但是实际上还是链接了。但是这是什么时候链接上的呢?

我们再看libstdc++的链接库发现:

$ ldd /usr/lib32/libstdc++.so.6
    linux-gate.so.1 =>  (0xf7f92000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7da6000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7bf0000)
    /lib/ld-linux.so.2 (0xf7f94000)
    libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf7bd3000)

看见没有!原来是libstdc++已经链接了libm库,这也就解释了为什么C++代码中不需要手动指定链接数学库libm。

总结:

通过前面的内容我们总结如下:

  • C代码编译时,通常会默认链接libc库

  • C++代码编译时,通常会默认链接libstdc++库

  • 由于libstdc++中有依赖一些数学函数或者libc库中的函数,因此默认链接了libc库和libm库。

推荐阅读

【1】终于整理齐了,电子工程师“设计锦囊”,你值得拥有!

【2】半导体行业的人都在关注这几个公众号

【3】10种常用的软件滤波方法及示例程序

【4】如何着手电源设计?3种经典拓扑详解(附电路图、计算公式)

b58cf886c1c8532d93d600c387502b8a.gif

你和大牛工程师之间到底差了啥?

加入技术交流群,与高手面对面 

添加管理员微信

5bfa3ae166c80be3e9872f051242c192.png

加入“中国电子网微信群”交流

486ccc1f52eb4bebc9b5031e46ff9f37.gif

具体加群详情请戳

→“中国电子网技术交流群” ←

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值