`
weihe6666
  • 浏览: 443536 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C+ __cplusplus 剖析

    博客分类:
  • C++
阅读更多
__cplusplus 剖析  


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

    #ifdef __cplusplus
    extern "C" {
    #endif

    //一段代码

    #ifdef __cplusplus
    }
#endif

为何会有__cplusplus 和extent "C" ?

这样的代码到底是什么意思呢?首先,__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。

  明白了加入与不加入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"来说明。



C++中因为函数可以重载:
int   a(char)
int   a(int)
int   a(double)...
所以,在编译后的代码里,三个a()是不同的函数名如a_char_xxx,a_in_xxx,a_double_xxx等等.

要去掉后面的一大串符号只要在a()前面加上exter   "C "即可

在DLL的对外接口函数中,必须用exter   "C "   限制,否则,外部调用者根本不知道你的真正函数名.
分享到:
评论

相关推荐

    #ifdef __cplusplus深度剖析

    "#ifdef __cplusplus深度剖析" 本文将深入探讨`#ifdef __cplusplus`语句的用途和机理,以及在C++编程中extern "C"的必要性。 首先,让我们来了解`#ifdef __cplusplus`语句的含义。在C++编程中,`__cplusplus`是一...

    解译#ifdef __cplusplus

    ### 解析 `#ifdef __cplusplus` 与 `extern "C"` 的作用 #### 一、引言 在跨语言编程的场景中,特别是在混合使用 C 和 C++ 编程时,经常会遇到 `#ifdef __cplusplus` 以及 `extern "C"` 这样的预处理器指令和...

    c_and_cplusplus_program

    标题 "c_and_cplusplus_program" 涵盖了两个编程语言——C和C++的应用,主要涉及数据处理、排序算法以及面向对象编程的概念。在这个项目中,开发者通过编写C程序来提升对函数调用和数据操作的理解,同时通过C++程序...

    C0_Complier_CPlusPlus:由 C++ 编写的 C0 编译器

    这个C0_Complier_CPlusPlus项目是一个使用C++实现的C0编译器,它涵盖了编译器设计中的关键阶段,包括词法分析、语法分析和符号表管理。 1. **词法分析**:词法分析(也叫扫描或词法分解)是编译器的第一步,它将源...

    cplusplus-tutorial_nightiiz_c++手册_cplusplus教程_源码.zip

    C++源自C语言,但扩展了许多特性,如类、模板、异常处理和命名空间等。C++的基础部分包括变量、数据类型、运算符、控制流(如if语句、switch语句、循环)、函数以及数组。理解这些基础知识是学习C++的第一步。 二、...

    C语言代码用在c++环境中

    #### 关键知识点:`#ifdef __cplusplus`、`extern "C"`及函数命名差异 在软件开发过程中,经常需要将已有的C语言代码集成到C++项目中,或者反之亦然。由于C++语言的设计初衷之一是为了向前兼容C语言,因此在C++中...

    c与c++头文件兼容宏定义

    通过上述讨论可以看出,通过合理利用`__cplusplus`宏和`extern "C"`关键字,我们可以轻松实现C和C++代码之间的互操作性。这不仅有助于提高代码的复用率,还能够简化项目管理过程。在实际应用中,建议开发者根据具体...

    C和C++相互调用的小技巧

    为了确保C++代码能够识别并调用C语言中的函数,或者C代码可以调用C++的函数,我们需要使用`extern "C"`声明来告诉C++编译器,这部分代码应该按照C语言的命名约定来处理。 #### 头文件的预处理器指令 在头文件中,...

    cplusplus.com网站/reference

    C++是一种强大的、面向对象的编程语言,由Bjarne Stroustrup在1983年基于C语言发展而来。它在C的基础上增加了类、模板、异常处理、命名空间等特性,使得程序设计更加灵活和高效。`cplusplus.com`是一个专门提供C++...

    C+编程网站

    1. **DZone Snippets (http://snippets.dzone.com/tag/c)**:这个平台汇集了大量C语言的源代码片段,对于解决具体编程问题或学习特定技术有极大帮助。 2. **Hotscripts ...

    c和c++互操作

    ### C与C++互操作详解 ...通过以上分析可以看出,`extern "C"`是实现C与C++互操作的关键。通过合理地使用`extern "C"`,开发者可以在不同的编程环境中无缝地使用同一份代码,从而提高代码的复用性和灵活性。

    精通MATLAB与C/C++混合程序设计光盘

    《精通MATLAB与C/C++混合程序设计》一书由刘维光编著,主要针对在科学研究和工程计算中常用到的MATLAB与C/C++混合编程技术进行深入讲解。这本书的第二版提供了丰富的实例和实用技巧,帮助读者熟练掌握这两种语言的...

    CPlusPlus_Projects:刷新和修改C ++

    在"CPlusPlus_Projects"这个项目中,我们主要关注的是刷新和更新C++编程技能。C++是一种强大的、通用的编程语言,它以其面向对象的特性、高效的性能和丰富的库支持而闻名。该项目可能旨在帮助开发者熟悉现代C++的...

    test_c_plusplus

    通过分析这些文件,我们可以更深入地了解如何在iOS环境中有效地结合C++和Objective-C。 总之,"test_c_plusplus"项目展示了如何在iOS开发中融合C++的效率和Objective-C的便利性,这对于提升应用性能、实现复杂算法...

    C语言面试问答题

    ### C语言面试问答题知识点详解 #### 1. 头文件中的ifndef/define/endif的作用 **知识点:** - 在C语言中,头文件是非常重要的组成部分,它们包含了函数的声明和其他预处理指令。 - `#ifndef`, `#define`, 和 `#...

    CPlusPlus:学习C ++

    C++是一种强大的、通用的编程语言,由Bjarne Stroustrup在1983年基于C语言开发,旨在提供更高级别的抽象和更高效的操作。C++是面向对象的,但也支持函数式、泛型编程和过程式编程风格。它是现代软件开发中的基石之一...

    CPlusPlus:C ++编程语言的源代码-C language program source code

    C++是一种强大的、通用的编程语言,它是C语言的扩展,增加了面向对象和泛型编程的概念。这个压缩包“CPlusPlus:C ++编程语言的源代码”很可能包含了用于教学或学习目的的C++源码示例,这为理解C++语言的语法、结构和...

    HCopy.rar_HTK_hcopy_hcopy.c_htk hcopy 封装

    为了解决这些问题,开发者可能需要使用条件编译指令,如`#ifdef _cplusplus`来区分C++环境,或者避免使用不兼容的特性,确保代码在C和C++环境下都能正常编译和运行。 在“HCopy.rar”这个压缩包中,包含的可能就是...

Global site tag (gtag.js) - Google Analytics