那谁的技术博客

感兴趣领域:高性能服务器编程,存储,算法,Linux内核
随笔 - 210, 文章 - 0, 评论 - 1183, 引用 - 0
数据加载中……

探索C++的秘密之一详解extern "C"

       时常在cpp的代码之中看到这样的代码:

#ifdef __cplusplus
extern "C" {
#endif

//一段代码

#ifdef __cplusplus
}

#endif


        这样的代码到底是什么意思呢?首先,__cplusplus是cpp中的自定义宏,那么定义了这个宏的话表示这是一段cpp的代码,也就是说,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern "C"{和}处理其中的代码.

        要明白为何使用extern "C",还得从cpp中对函数的重载处理开始说起.在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等.而在C中,只是简单的函数名字而已,不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的.

         比如下面的一段简单的函数,我们看看加入和不加入extern "C"产生的汇编代码都有哪些变化:

int f(void)
{
    
return 1;
}


       在加入extern "C"的时候产生的汇编代码是:

    .file    "test.cxx"
    .text
    .align 
2
.globl _f
    .def    _f;    .scl    
2;    .type    32;    .endef
_f:
    pushl    
%ebp
    movl    
%esp, %ebp
    movl    $
1%eax
    popl    
%ebp
    ret


但是不加入了extern "C"之后

 .file "test.cxx"
 .text
 .align 
2
.globl __Z1fv
 .def __Z1fv; .scl 
2; .type 32; .endef
__Z1fv:
 pushl 
%ebp
 movl 
%esp, %ebp
 movl $
1%eax
 popl 
%ebp
 ret


        两段汇编代码同样都是使用gcc -S命令产生的,所有的地方都是一样的,
唯独是产生的函数名,一个是_f,一个是__Z1fv.

        OK,明白了加入与不加入extern "C"之后对函数名称产生的影响,我们继续我们的讨论:为什么需要使用extern "C"呢?
        C++之父在设计C++之时,考虑到当时已经存在了大量的C代码,为了支持原来的C代码和已经写好C库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略.

       试想这样的情况:一个库文件已经用C写好了而且运行得很良好,这个时候我们需要使用这个库文件,但是我们需要使用C++来写这个新的代码.如果这个代码使用的是C++的方式链接这个C库文件的话,那么就会出现链接错误.我们来看一段代码:首先,我们使用C的处理方式来写一个函数,也就是说假设这个函数当时是用C写成的:

//f1.c
extern "C"
{
void f1()
{
    
return;
}

}

编译命令是:gcc -c f1.c -o f1.o   产生了一个叫f1.o的库文件.
再写一段代码调用这个f1函数:

// test.cxx
//这个extern表示f1函数在别的地方定义,这样可以通过
//编译,但是链接的时候还是需要
//链接上原来的库文件.
extern void f1();

int main()
{
    f1();

    
return 0;
}


通过gcc -c  test.cxx -o test.o 产生一个叫test.o的文件.
然后,我们使用gcc test.o f1.o来链接两个文件,可是出错了,错误的提示是:
test.o(.text + 0x1f):test.cxx: undefine reference to 'f1()'
也就是说,在编译test.cxx的时候编译器是使用C++的方式来处理f1()函数的,但是实际上链接的库文件却是用C的方式来处理函数的,所以就会出现链接过不去的错误:因为链接器找不到函数.
      因此,为了在C++代码中调用用C写成的库文件,就需要用extern "C"来告诉编译器:这是一个用C写成的库文件,请用C的方式来链接它们.
      比如,现在我们有了一个C库文件,它的头文件是f.h,产生的lib文件是f.lib,那么我们如果要在C++中使用这个库文件,我们需要这样写:

extern "C"
{
#include 
"f.h"
}

回到上面的问题,如果要改正链接错误,我们需要这样子改写test.cxx:

extern "C"
{
extern void f1();
}


int main()
{
    f1();

    
return 0;
}


重新编译并且链接就可以过去了.

总结:C和C++对函数的处理方式是不同的.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明.

 

 

 

posted on 2006-01-14 23:52 那谁 阅读(4909) 评论(12)  编辑 收藏 引用 所属分类: C\C++

评论

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

写得不错。

C++因为函数有很多种,成员函数拉,template函数拉,所以他会对函数名称进行变换。
C很单纯,一般也就是在函数名称前面加上一个_就好了。
2006-01-16 10:06 | 小明

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

学习哈:)
2006-01-16 17:37 | uestc

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

extern "C"是使C++能够调用C写作的库文件的一个手段
--------------
同样,extern "C"也是使C能够调用C++库文件的一个手段。只不过,C不能直接包含带extern "C"的C++头文件,需要用extern声明一下要使用的函数。
2006-01-19 17:21 | 力为

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

不同编译器处理这种修饰名的方法是不同的,这就是为什么有些人不喜欢发布类库的原因,换个编译器,就只能重新编译了。
2006-01-22 16:38 | feelapi

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

总结一句话:就是为了方便在C++程序中调用C程序
2006-01-24 17:00 | 流氓

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

这篇好像完整点
http://blog.csdn.net/billyang1983/archive/2006/01/04/570498.aspx
2006-02-25 01:43 | Kemin

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

写的乱七八糟的,
2006-04-08 14:01 |

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

这篇写的最好最全
http://blog.csdn.net/keensword/archive/2005/06/23/401114.aspx
2006-05-12 14:21 | mem

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

你好,我们是一家致力于中国互联网的本地搜索、手机地图和位置服务的创业型软件公司。入选2005年最值得关注的50家商业网站(www.mapabc.com)。Google、Sina、微软、中搜、阿里巴巴、中国移动等著名的公司都是图盟科技的合作伙伴,因业务需要,需要招聘一些对于C++方面比较熟悉的人,我看了你的blog,希望和你交流一下,如果你有意在北京工作,而且愿意从事一些有挑战性的工作的话,请将简历发送到hyla_he@126.com,我会与你联系,谢谢
2006-07-05 13:04 | hyla

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

嗷嗷,抱歉,一年前刚刚离开北京现在在深圳,哈~~
2006-07-05 17:34 | 创系

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

@力为


编写C/C++公用的用extern "C"头文件也是可以的。
#ifdef __cplusplus
/*
C++专用部分,包括 class声明, 公共函数的重载等。
*/
extern "C" {
#endif /*__cplusplus*/
/*
C / C++ 公共部分,包括结构声明,函数声明,变量声明。
*/

#ifdef __cplusplus
}
#endif /*__cplusplus*/
2006-08-22 17:27 | yihao

# re: 探索C++的秘密之一详解extern "C"  回复  更多评论   

http://donna-matura-zoccola.fatte-tun.info
http://dvd-de-cul.culs-ugx.info
http://scopare-cinese-foto.sculaccia-tun.info
http://elle-suce-son-gendre.succhiano-ugx.info
http://brazil-fetish-video.sculaccia-tun.info
http://baise-amatrice.senegalese-ugx.info
http://coppia-trans-escort-romagna.fatte-tun.info
http://video-de-sexe-gratuitement.succhiano-ugx.info
http://pokemon-porno.sculaccia-tun.info
http://video-sexe-amateur-gratuit.senegalese-ugx.info
http://ciccione-scopano.sculaccia-tun.info
http://sexe-amateur-francais.succhiano-ugx.info
http://eva-henger-gratis-porno-video.gradis-tun.info
http://france-sexe-gratuit.culs-ugx.info
http://arrapanti-casalinghe.sculaccia-tun.info
http://telechargement-gratuit-video-sexe-gratuite.senegalese-ugx.info
http://intervista-gay-escort.sculaccia-tun.info
http://gratuit-porno-pute-video.senegalese-ugx.info
http://fotoracconti-erotici-amatoriali.sculaccia-tun.info
http://rencontre-sexe-en-moselle.senegalese-ugx.info
http://racconto-o-storia-porno.gradis-tun.info
http://bresilienne-qui-baise.culs-ugx.info
http://foto-orgia-tettona.fatte-tun.info
http://karine-sexe.culs-ugx.info
http://video-bella-donna-scopata.fatte-tun.info
http://sexe-moselle.culs-ugx.info
http://foto-sesso-vecchio-gratis.gradis-tun.info
http://mangas-land-sexe-gratuit.succhiano-ugx.info
http://sakura-sexy-gratis.fatte-tun.info
http://suce-bite-.com.succhiano-ugx.info
http://sborra-gola.sculaccia-tun.info
http://over-blog-sexe-mature.culs-ugx.info
http://bocchino-hard.fatte-tun.info
http://la-salope-du-jour.succhiano-ugx.info
http://hard-core-video-amatoriale.fatte-tun.info
2007-12-30 08:49 | sdgsdg

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理