• extern "C" 有关问题


      之前帮老板编译一个库的代码,遇到了一些问题,后来发现问题出现在extern "C"语法上。 

      1. C/C++语法extern 关键字

      extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。”----百度百科。值得注意的是extern int a,仅是一个声明, 可以在程序中出现多次,并没有分配存储空间,然而变量a作为全局变量,变量a的定义仅能出现一次。

    // A.cpp
    int i;
    int main()
    {
        return 0;
    }
    
    
    // B.cpp
    int i = 100;

      编译A.cpp文件,B.cpp文件不会提示有错误,在编译阶段,各个文件中定义的全局变量相互是不透明的,编译A时觉察不到B中也定义了i,同样,编译B时觉察不到A中也定义了i。但是在链接阶段,A与B文件融合在一起,全部变量都存在程序的静态存储区域,因此会有如下报错:

                                     

      但是,我们直接使用B.cpp中定义的变量,编译器并没有先见之明,在编译阶段无法知道变量定义在文件中,如下代码:

    // A.cpp
    //int i;
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        cout<<i;    
        return 0;
    }
    
    // B.cpp
    int i=100;

    将会提示:“错误 1 error C2065: “i”: 未声明的标识符 d:程序 estexterna.cpp 9 1 extern”

      为此,关键字"extern",便发挥了它的作用,在A.cpp文件中添加声明:extern int i;

    // A.cpp
    //int i;
    extern int i;
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        cout<<i;    
        return 0;
    }
    
    // B.cpp
    int i=100;

    程序正常运行输出:100;

      2. C++ extern "C" 语法缘由

      C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y );
    该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。
      在被编译的c++程序中,如果调用了其他的库的函数,则这个函数名也是照加了附加信息的函数名来调的,这样,如果这个库是c方式编译的,那么在库中的函数名是不带附加信息的,这样的调用链接就会失败,因为函数名不对应导致找不到,出现连接错误
      为了解决这个问题,C++引入extern “C”。extern “C”是告诉编译器:这是一个用C写成的库文件,请用C的方式来链接它们。

      3. 一般用法

      经常在项目文件看到的extern “C”的用法:

     #ifdef __cplusplus
     extern "C" {
     #endif
     
     // 代码
    
     #ifdef __cplusplus
     }
     #endif

      代码部分可以是:调用库函数头文件(ie. #include <c.h>、调用函数声明(ie. extern int add())、一段函数代码实现。需要注意宏__cplusplus,标志着编译器将会把代码按C还是C++语法来解释,目的是这个文件既可以被C调用也可以被C++调用。因为C并没有extern “C”语法,因此如果不加宏编译,编译器会报错的。

  • 相关阅读:
    魔兽70TBC猎人常用宏
    魔兽70TBC猎人宝宝技能汇总
    redis常用概念
    mongodb分片集群开启安全认证
    mongodb集群搭建(分片+副本)
    mongodb 用户权限控制
    greenplum数据迁移
    greenplum资源队列
    GreenPlum 集群常用命令
    COCOS 实现Player玩家控制的左右控制,实现马里奥一样的移动
  • 原文地址:https://www.cnblogs.com/wangbogong/p/3140359.html
Copyright © 2020-2023  润新知