C++函数重载与编译链接

前言

        C++支持函数重载,C语言不支持函数重载,它们的区别在于编译器对函数编译的实现不一样。

编译链接

        要想明白这个问题,我们首先来简单认识一下编译链接。我们平时写的C,C++代码都是需要通过编译链接生成可执行文件的。

        为什么需要编译链接?因为我们写的代码CPU是不能直接识别到的,需要通过编译把我们写的代码转换成汇编语言,汇编语言再转换成二进制的机器语言,然后把项目中的多个二进制文件链接起来生成可执行程序。

        下面我们来更详细的了解一下编译链接的具体过程。

编译阶段

        编译阶段分为预处理,编译,汇编三个阶段。

预处理

        编译阶段首先要做的一件事是预编译。预处理,就是在为编译阶段做铺垫。要做的工作有:头文件展开、宏替换、条件编译、去掉注释等等。

        头文件展开就是在源文件中把包含的相应头文件拷贝到源文件中,头文件由于以及包含到源文件中了所以不会参加编译以及后续的阶段。

         条件编译是指的是我们在编译的时候可以根据某些条件选择是否编译某一段代码。

编译

        预处理完成之后要进行编译,编译主要是检查语法正确性并转换为汇编代码。

汇编

        汇编阶段把汇编代码转换为机器语言,并生成符号表。符号表主要是在链接的时候发挥作用, 在很多时候函数声明和定义是分离的是在2个不同的文件中,这时候符号表中就有声明和定义的映射关系,供在链接阶段编译器去查找。

链接阶段

        把编译阶段完成后的二进制文件链接起来生成一个可执行程序。

C++编译器函数名修饰规则

        C语言的编译器在汇编代码中定义一个函数的时候直接是使用它的函数名。但是在C++中汇编代码定义一个函数的时候是根据函数名修饰规则去定义的。

        下面是在Linux环境下使用gcc、g++作为编译器实现的样例。Linux下编译后生成a.out可执行文件。objdump可以查看对应的汇编代码。

C语言汇编

[root@VM-0-13-opencloudos ~]# vim test.c
#include <stdio.h>

void Function(int a)
{
        printf("%d\n", a);
}

int main()
{
        int a = 10;
        Function(a);
        return 0;
}
[root@VM-0-13-opencloudos ~]# gcc test.c
[root@VM-0-13-opencloudos ~]# objdump -S a.out
....
0000000000400596 <Function>:
  400596:       55                      push   %rbp
  400597:       48 89 e5                mov    %rsp,%rbp
  40059a:       48 83 ec 10             sub    $0x10,%rsp
  40059e:       89 7d fc                mov    %edi,-0x4(%rbp)
  4005a1:       8b 45 fc                mov    -0x4(%rbp),%eax
  4005a4:       89 c6                   mov    %eax,%esi
  4005a6:       bf 78 06 40 00          mov    $0x400678,%edi
  4005ab:       b8 00 00 00 00          mov    $0x0,%eax
  4005b0:       e8 eb fe ff ff          callq  4004a0 <printf@plt>
  4005b5:       90                      nop
  4005b6:       c9                      leaveq
  4005b7:       c3                      retq
....

C++汇编

[root@VM-0-13-opencloudos ~]# vim test.cpp
#include <stdio.h>

void Function(int a)
{
        printf("%d\n", a);
}

void Function(int a, double b)
{
        printf("%d %f\n", a, b);
}

int main()
{
        int a = 10;
        int b = 10.1;
        Function(a);
        Function(a, b);
        return 0;
}
[root@VM-0-13-opencloudos ~]# g++ test.cpp
[root@VM-0-13-opencloudos ~]# objdump -S a.out
00000000004005b6 <_Z8Functioni>:
  4005b6:       55                      push   %rbp
  4005b7:       48 89 e5                mov    %rsp,%rbp
  4005ba:       48 83 ec 10             sub    $0x10,%rsp
  4005be:       89 7d fc                mov    %edi,-0x4(%rbp)
  4005c1:       8b 45 fc                mov    -0x4(%rbp),%eax
  4005c4:       89 c6                   mov    %eax,%esi
  4005c6:       bf d8 06 40 00          mov    $0x4006d8,%edi
  4005cb:       b8 00 00 00 00          mov    $0x0,%eax
  4005d0:       e8 eb fe ff ff          callq  4004c0 <printf@plt>
  4005d5:       90                      nop
  4005d6:       c9                      leaveq
  4005d7:       c3                      retq

00000000004005d8 <_Z8Functionid>:
  4005d8:       55                      push   %rbp
  4005d9:       48 89 e5                mov    %rsp,%rbp
  4005dc:       48 83 ec 10             sub    $0x10,%rsp
  4005e0:       89 7d fc                mov    %edi,-0x4(%rbp)
  4005e3:       f2 0f 11 45 f0          movsd  %xmm0,-0x10(%rbp)
  4005e8:       f2 0f 10 45 f0          movsd  -0x10(%rbp),%xmm0
  4005ed:       8b 45 fc                mov    -0x4(%rbp),%eax
  4005f0:       89 c6                   mov    %eax,%esi
  4005f2:       bf dc 06 40 00          mov    $0x4006dc,%edi
  4005f7:       b8 01 00 00 00          mov    $0x1,%eax
  4005fc:       e8 bf fe ff ff          callq  4004c0 <printf@plt>
  400601:       90                      nop
  400602:       c9                      leaveq
  400603:       c3                      retq

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值