通常,在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改为:
-
/*-----------c.h--------------*/
-
#ifndef _C_H_
-
#define _C_H_
-
#ifdef __cplusplus
-
extern "C" {
-
#endif
-
-
extern int add(int, int);
-
-
#ifdef __cplusplus
-
}
-
#endif
-
-
#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”。
阅读(6554) | 评论(0) | 转发(2) |