【C++】extern "C"详解
  0nB32TkOQVir 2023年11月02日 112 0
C++

先说结论 :  extern "C"只影响到链接期的name mangling

什么是name mangling?

    请看 :  C++函数重载的实现机制之name mangling - 知乎 (zhihu.com)

举个例子 :

// external.h
#ifdef __cplusplus
extern "C" {
#endif

void external();

#ifdef __cplusplus
}
#endif
// external.cc
#include "external.h"

template <typename T> // 这明显是C++特性, gcc是无法编译的
void external()
{
    T a;
}
// main.c
#include "external.h"

int main()
{
    external();
}

在这里 : main函数里面调用了c++函数external(), 如果这个函数没被 extern "C"包裹, 会出现"undefined reference to"的错误.

这是因为g++、clang++都优先判断后缀名 ( 除非自己改option ), 就会对external.cc文件进行C++方式编译 : 

  由于c++重载机制的存在, 编译器只能在你命名之后 再悄悄重新给函数做个标记, 这个标记名也是有规则的, 比如g++, [ _Z + 函数名长度 + v / i ...标记符 ] .

  external()函数被compiler赋予一个"符号", 如果是gcc, 这个符号就是external;

                       如果是g++, 这个符号是 _Z8externalv 或者_Z8externali;

                            而clang++更夸张, 变成了"?external@@YAHXZ"或者"?external@@YAHH@Z"这种怪物.

然后把obj文件中定义和引用的global variable和function存到一张"符号表"中方便链接器的工作.

------------------------------------------------------------------------------------------------------------------

             名字             |               类型                |          是否可被外部引用            |             区域

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      _Z8externalv     |           定义, 引用            |                       可                       |           代码段

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      _Z8externali      |           定义, 引用            |                       可                       |           代码段

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    main            |               定义                 |                                                  |

-------------------------------------------------------------------------------------------------------------------

  链接器说"我开始找了 ! ", 然后给main函数找external(), 发现没有啊, 它干不了了, "undefined reference to external".

  如果你把它用 extern "C" 声明,  链接器才能找到c版本的external(), 加上依赖库/模块 全打包起来.    拿gnu来说吧, c程序会打包libgcc.a静态库,c++程序则会打包很多libstdc++.a的东西和一些各式各样的依赖, 这也是一般c++程序大小都要pure c大的原因, 在MCU上这种差距尤为明显.

 

所以, 你extern "C"包裹函数的声明, 并不会改变函数体内语句的实际编译方式, 因为它的定义仍在.cc文件里, g++仍会优先将它以c++的方式编译. 但是这个函数的声明会以c的方式编译,c程序的也能通过链接器找到.

 

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

上一篇: C++基础2 下一篇: <六>指向类成员的指针
  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  8Tw5Riv1mGFK   2024年05月01日   80   0   0 C++
  BYaHC1OPAeY4   2024年05月08日   58   0   0 C++
  yZdUbUDB8h5t   2024年05月05日   44   0   0 C++
  oXKBKZoQY2lx   2024年05月17日   59   0   0 C++
0nB32TkOQVir
作者其他文章 更多