剖析extern "C"

env:
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)


在c++中调用c语言写的模块时经常在头文件中加入这样一段预处理命令:

#ifdef __cplusplus
extern "C" {   
#endif
/*some c header or declaration*/
#ifdef __cplusplus
}
#endif

之所以要引入extern "C"(注: 引号中是大写的C), 是因为c++中存在overload即函数重载, 为了区别函数名相同参数不同的函数, c++编译器在编译期间会将函数名和函数参数作为整体进行编译来得到链接所需的符号;c语言中没有overload, 编译器直接以函数名作为链接符号, 无视函数名后面的参数。


请看以下例程:

例程一:

有以下2个模块main.cc和add.c, 在main.cc中调用add.c中的函数add

/*main.cc模块*/
#include <iostream>

//extern "C"
//{
  extern int add(int a, int b);
//}

int main(int argc, char * argv[])
{
  int s;
  
  s = add(1, 2); 
  std::cout << "s = " << s << std::endl;  

  return 0;
}
/*add.c模块*/
int add(int a, int b)
{
  return a + b;
}

执行以下命令:
g++ -c main.cc
gcc -c add.c
g++ main.o add.o -o test
则会报链接错误:
undefined reference to `add(int , int)', 意为找不到该函数定义。
执行objdump -t main.o查看符号表发现main.cc中调用的外部函数add已被编译为"00000000 UND 00000000 _Z3addii"(add后面的2个i为参数int, int 的缩写), 明显函数编译后的链接符号与函数参数是有关系的。再执行objdump -t add.o查看符号表发现add函数对应的符号就是add。显而易见链接器肯定找不到链接符号为_Z3addii的函数, 因为我们从来没有定义过。

试想: 其他模块不动将add.c中的add函数改名为_Z3addii是否可以链接成功呢? 答案是肯定的, 但是这么写代码有啥意义呢?

例程二:

有以下2个模块main.cc和add.c, 在main.cc中调用add.c中的函数add
将例程一中extern "C"的注释打开, 如下所示:

/*main.cc模块*/
#include <iostream>

extern "C"
{
  extern int add(int a, int b);
}

int main(int argc, char * argv[])
{
  int s;
  
  s = add(1, 2);
  std::cout << "s = " << s << std::endl;  

  return 0;
}
/*add.c模块*/
int add(int a, int b)
{
  return a + b;
}

执行以下命令:
g++ -c main.cc
gcc -c add.c
g++ main.o add.o -o test
编译链接正常, 执行可执行文件./test, 即可看到我们想要的结果:s = 3。此刻我们再次执行命令objdump -t main.o看到main.cc中的调用的外部函数add被编译为:"UND 00000000 add", 符号和函数名完全一致而没有添加一些奇怪的东西!

总结:

  extern "C"就是要告诉c++编译器大括号里面声明的函数要按照c语言的方式编译成链接需要的符号。这样c++在链接的时候才能找到对应的c函数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 8,188评论 0 27
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 3,365评论 0 3
  • 玟瑾/文 食客众多、就餐需要排队领号、总在翻台,人们就会说这个饭馆人气十足,而当一个人总表现出一些影响力、具有很强...
    我是玟瑾阅读 732评论 0 1
  • 青春说起来好像是一个褒义词,仿佛它就该是绚烂的或难忘或,,,好多词可以形容它,可我却只想任性的只写自己的青春。 我...
    微窨一世阅读 273评论 5 0
  • 小时候,我们总是亦步亦趋的跟着父母,唯恐做错了事。上学后,模仿老师走路、说话,因为觉得老师超级正确。工作了,深知责...
    叶塞尼娅阅读 684评论 0 0

友情链接更多精彩内容