关于编译器的符号修饰与函数签名

         在《程序员的自我修养---链接、装载与库》这本书中,较为详细的介绍了编译器底层的一些工作机制。

         其中涉及到这样一段代码:

    1  #include <stdio.h>

     2
     3  namespace myname
     4  {
     5      int var = 42; //经由GCC编译器的符号修饰后变为 _ZN6myname3varE(供连接器链接使用的符号)
     6  }
     7
     8  extern "C" double _ZN6myname3varE;
     9
    10  int main()
    11  {
    12      printf("%d\n",_ZN6myname3varE);
    13      return 0;

    14  }

编译并运行:

g++ t.c -o a.out

./a.out

得到输出结果:

42

若将第8行注释掉,编译会产生错误:

t.c: In function 'int main()':
t.c:12: error: '_ZN6myname3varE' was not declared in this scope

若将第3-6行注释掉(第8行不注释),编译也会产生错误:

/tmp/cc0asb7n.o: In function `main':
t.c:(.text+0x13): undefined reference to `myname::var'
collect2: ld returned 1 exit status 

        由此可见,此程序成功运行的关键在于第8行引入了外部变量_ZN6myname3varE,而保证了第12行编译时不会出错,并且12行的_ZN6myname3varE符号不会进行符号修饰(编译时),而是保持不变,而在连接时其意义相当于myname::var,即引用(链接)了namespace命名空间中的变量var。

       本质上还是体现了编译系统或者说计算机体系的分层思想,在这段代码中的具体体现就是,通过extern “C”这条语句成功的欺骗了编译器,使第12行成功的通过了编译,为连接器做好了链接准备。

附图(GCC基本C++名称修饰规则):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值