zoukankan      html  css  js  c++  java
  • C和C++混合编程之 extern “C”的使用

    C和C++混合编程之 extern “C”的使用

    首先要明白:

    C++号称是C语言的超集,也确实,从语言的基本语法上,C++是包含所有C语言的语法的,而且C++为了兼容C,连C语言的标准库也被纳入到C++的标准库中,比如在C++中我们仍然可以使用<stdio.h>,它就是C++标准库的一部分(注意最好用新的标准<cstdio>,而不是老的<stdio>)。

    但是,C++和C语言的编译器在有些地方还是有差别的。比如,C++是支持面向对象的特性(尽管C++被称为不彻底的面向对象语言),面向对象就要支持函数重载,而函数重载的实现和C++编译器是分不开的。

    比如有:

    int max(int a, int b);

    double max(double a,double b);

    这两个函数。

    这两个函数同时存在,在C语言中是不可以的,因为C语言不支持重载,但是在C++中完全没有问题,因为C++是支持重载的。

    那么为什么会这样呢?

    这要从编译器的角度来看:

    C编译器将int max(int a,int b)函数编译后,在符号库中的名字为_max(不同编译器可能有不同的形式)

    C编译器将double max(double a,double b)函数编译后,在符号库中的名字也为_max。所以在C语言中,这两个函数是不能共存的的,编译时会提示错误。

    但是C++编译器则不同

    C++编译器将int max(int a, int b)编译后,在符号表中的名字为:

    _max_int_int

    而另一个则为_max_double_double。这两者并不冲突。

    这也是C++支持函数重载的根本原因。不过,这也从另一面说明了:函数重载其实不是多态,顶多算是编译时多态。

    在C++和C混合编程时:

    在C++和C语言混合编程时,前面已经说过,C++的语法是完全包含C语言的语法的,所以不用担心语法上出现什么问题。出现问题的主要原因在编译和链接时。

    思考这样一件事情:

    我们在Linux下编程的时候,经常会用到内核的库,我们知道Linux内核使用C语言写的。如果这些库采用了C语言的编译器进行编译,而我们的程序是用C++开发的,要用C++进行编译,那么会出现什么问题?

    比如:

    我们有个.c文件p.c,内容如下:

    #include <stdio.h>
    
    void print(int a,int b)
    {
           printf("这里调用的是C语言的函数:%d,%d
    ",a,b);
    }

    我们用gcc –c命令编译它,生成p.o文件

    然后我们又p.h文件,里面是print函数的原型声明,如下:

    void print(int a,int b);

    我们又有main.cpp文件,内容如下

    #include <iostream>
    
    using namespace std;
    
    #include "p.h"
    
    int main()
    {
           cout<<"现在调用C语言函数
    ";
           print(3,4);
           return 0;
    
    }

    这次我们用g++ -c进行编译,生成main.o文件

    然后我们用g++链接两个.o文件,这时我们会发现,报错:

     

    这时为什么呢?

    因为:

    p.c我们使用的是C语言的编译器gcc进行编译的,其中的函数print编译之后,在符号表中的名字为 _print

    而我们链接的时候采用的是g++进行链接,也就是C++链接方式,程序在运行到调用print函数的代码时,会在符号表中寻找_print_int_int(是按照C++的链接方法来寻找的,所以是找_print_int_int而不是找_print)的名字,发现找不到,所以会t提示“未定义的引用”

    此时如果我们在对print的声明中加入 extern “C” ,这个时候,g++编译器就会按照C语言的链接方式进行寻找,也就是在符号表中寻找_print,这个时候是可以找到的,是不会报错的。比如我们修改p.h为:

    extern "C" void print(int a,int b);

    这是结果为:

     

    所以extern “C” 用到函数声明之前,它的作用就是告诉编译器,对于该函数的链接要采用C语言编译器的链接方式,也就是告诉编译器找_fun,而不是_fun_int_int。

    如果有多个函数声明都需要在前面加extern “C”,那可以用extern “C”{}的形式。

    如果你觉得对你有用,请赞一个吧

  • 相关阅读:
    java_oop_方法2
    POJ 3276 Face The Right Way(反转)
    POJ 3276 Face The Right Way(反转)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3061 Subsequence(尺取法)
    POJ 3061 Subsequence(尺取法)
    HDU 1222 Wolf and Rabbit(欧几里得)
  • 原文地址:https://www.cnblogs.com/qingergege/p/7478864.html
Copyright © 2011-2022 走看看