extern "C"的小结 来自《程序员的自我修养》

extern "C"的小结 来自《程序员的自我修养》

  • C++为了与C兼容,C++可以使用关键字extern "C"来声明或者定义一个C符号:

    extern "C"{
        int func(int);
        int var;
    }```
      C\+\+会将extern "C"的大括号内的代码当做C语言代码**(.c文件)**处理,亦即在大括号中C\+\+的名称修饰机制将不起作用,不同的编译器有不同的名称修饰方法:
      1.如果是VC++平台,上述代码中的fun和var会被修饰(名称修饰)为_func和_var;
      2.但是如果是linux下的gcc编译器,前面的_也会被去掉,extern "C"里面的符号就是修饰后符号(为func和var)。
    【补充】gcc编译.c文件,因为是按照c方式编译,所以函数名不变;gcc编译.cpp文件,g\+\+编译.c文件,g\+\+编译.cpp文件,因为是按照c\+\+方式编译,所以函数名才会加上了附加信息。(当前编译器编译出来的目标文件和库文件(目标文件)应该是同样的编译器编译出来的)
    ps:单独声明某个函数或者是变量是C的符号,可以直接
    

    extern "C" int func(int);

  • extern "C"带来的问题
      我们经常遇到这样的情况:有些头文件声明了一些C语言的函数和变量,但是这个头文件可能被C语言或者是C++语言包含。例如:
      对于函数 void memset (void , int, size_t) 而言,如果不使用extern "C"**,考虑一以下两种情况:
      1.在C语言程序包含string.h的时候,如果用到了memset这个函数,编译器会进行正确的函数名称修饰memset(C语言的名称修饰,前面加),也可以正确的连接到C语言库中的memset符号。
      2.在C++程序中包含了memset函数,编译器编译器会认为这是一个C++函数,函数名就会被修饰为_Z6memsetPvii(C++的名称修饰可自行了解),这样的话,链接器就没办法在C语言的库中找到对应的符号地址。此时就必须使用extern "C"。

  • C与C++的兼容问题的实现
    方法是使用C++的宏__cplusplus

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

    含义是,如果是C++代码,那么memset会在extern "C"中被声明,如果是C代码就直接声明。

你可能感兴趣的:(extern "C"的小结 来自《程序员的自我修养》)