Chinaunix首页 | 论坛 | 博客
  • 博客访问: 170241
  • 博文数量: 78
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 287
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 02:49
文章分类
文章存档

2013年(23)

2012年(55)

分类: C/C++

2013-05-13 14:03:37

通常,在C语言的头文件中经常可以看到类似下面这种形式的代码:

 

#ifdef  __cplusplus

extern "C" {

#endif

/**** some declaration or so *****/ 

#ifdef  __cplusplus

    }

#endif  /* end of __cplusplus */


其中的extern "C"是什么意思呢?

    通过学习知道原来是c++函数调用c语言的函数模块时申明用c语言的符号表!因为c++为了实现函数的重载(相同的函数名不同的参数)会把函数如int add(int x,int y)定义为类似_Z3addii的符号表(函数名外加每个参数的类型,不同的编译器符号表可能不同,此为g++的符号表),而c的函数符号表为add(不同的编译器符号表可能不同,此为gcc的符号表)。故如果当c++代码调用c的函数时就会因为找不到对应的符号表而出错。

代码如下


C的头文件

/*-----------c.h--------------*/ 
#ifndef _C_H_ 
#define _C_H_ 
extern int add(int x, int y); 
#endif

C的源文件

/*-----------c.c--------------*/ 
int add(int x, int y)
{
   return x+y
}

C++的调用

/*-----------cpp.cpp--------------*/ 
#include "c.h" 
void main() 
{
  add(1, 0); 
}


编译时报错:(注:用g++时不会报错,下面解释)

$ gcc cpp.cpp c.c -lstdc++

/tmp/ccNJ5gxW.o: In function ‘main':

cpp.cpp:(.text+0x19): undefined reference to ‘add(int, int)'

collect2: ld returned 1 exit status


undefined reference to ‘add(int, int)'就表明未查找到_Z3addii的符号表(因为符号表示add)
注:-lstdc++ 申明用c++库

而将c.h改为:
  1. /*-----------c.h--------------*/
  2. #ifndef _C_H_
  3. #define _C_H_
  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif

  7. extern int add(int, int);

  8. #ifdef __cplusplus
  9. }
  10. #endif

  11. #endif /* _C_H_ */
$ gcc cpp.cpp c.c -lstdc++

源文件为*.c,__cplusplus没有被定义,extern "C" {}这时没有生效对于C他看到只是extern intadd(int, int);
add函数编译符号成add
源文件为*.cpp(或*.cc,*.C,*.cpp,*.cxx,*.c++), __cplusplus被定义 ,对于C++他看到的是 extern "C"  { extern  int add( int ,int);}编译器就会知道 add(1, 0);调用的C风格的函数,就会知道去找add符号而不是_Z3addii
因此编译正常通过。

查看生成的a.out文件的符号表会看到add符号
上图说明在加上extern “C”后 c++的函数就能正常使用c的函数模块了!

为什么用$ g++ cpp.cpp c.c 在不加extern “C”的情况下也正常通过编译?
   用g++会自动将c的模块中的符号表转换为_Z3addii这也是GNU compiler的强大之处,可是别的编译器也许就不这么智能了。所以在c/c++混合编程时还是最好加上extern “C”


阅读(961) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~