引言

由于不同的代码互相调用起来很容易出错,甚至同一种代码但由不同的编译器编译,为实现C++代码调用其他C语言代码,会在C语言代码的部分加上extern "C",表明这段代码需要按照类C的编译和连接规约来编译和连接,而不是C++的编译的连接规约。

extern "C"中的"C"指的不是一种语言,而是一种编译和链接的规约,表示符合C语言的编译和连接规约的任何语言,如Fortran、assembler等。所以并不能改变其语义,在编写被加上extern "C"的代码时还是要遵守C++的类型检测和参数转换规则。

该文章从以下方面解释extern "C"用法:

  • 1、extern "C"双重含义

    • 1.1、 extern
    • 1.2、"C"
  • 2、C与C++的相互调用
    • 2.1、 C++ 调 C
    • 2.2、C调 C++

1、extern "C"双重含义

extern "C" 包含双重含义,从字面上可见得它有两个部分,"extern"和"C"。

1.1、 extern

全局函数、变量等在所有的源文件是一致的,只能被定义一次,但可以被声明多次:

//sample1.c
int a = ;
//sample2.c
extern int a;

在以上代码sample2.c中使用的 a 是定义在sample1.c里的。变量 a 在所有文件中只能被定义一次否则出错,但可以被声明多次,每次声明要保持类型一致。sample2.c中的 extern 表示 a 变量在此仅仅是一个声明,而不是定义。

extern是C/C++语言中表明函数全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。

与extern对应的关键字是 static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

1.2、 "C"

被extern "C"修饰的变量和函数是按照类C语言方式编译和链接的。

C++作为一种面向对象的语言,C++支持函数重载,需要在函数名字中加入函数参数,而过程式语言C则不支持,所以函数名不会被更改。例如,当函数原型为:

void func ( int a , float b );

该函数被 C 编译器编译后在符号库中的名字为 _func,而C++编译器则将函数名中加入函数参数,变为 _func_int_float 。

同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

2、C与C++的相互调用

2.1、 C++ 调 C

C++中调用的C语言包含在C语言头文件时,可如此调用:

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

完整例子如下:

//c语言头文件:sample_c.h
#ifndef SAMPLE_C_H
#define SAMPLE_C_H
extern int plus( int a, int b);
#endif //c语言实现文件:sample_c.c
#include "sample_c.h"
int plus( int a, int b){
return a+b;
} //c++文件:sample_cpp.cpp
extern "C"{
#include "sample_c.h"
}
int main( int argc, int **argv){
plus( , );
}

2.2、 C 调 C++

C语言中不支持extern "C"声明,所以调用起C++来和C++调用C有点区别。

//C++头文件:sample_cpp.h
#ifndef SAMPLE_CPP_H
#define SAMPLE_CPP_H
extern "C" int plus( int a, int b);
#endif //C++实现文件:sample_cpp.cpp
#include "sample_cpp.h"
int plus( int a, int b){
return a+b;
} //C实现文件:sample_c.c
extern int plus( int a ,int b);//C语言中在此写#include "sample_cpp.h"会出错
int main(){
plus( , );
}

最新文章

  1. 【探索】在 JavaScript 中使用 C 程序
  2. 【nodejs笔记3】Express基本用法,和路由控制,和模板渲染ejs
  3. IE 8 下的 box-sizing 和 min-* 属性
  4. Java抽象类与接口的区别
  5. Apache Storm源码阅读笔记
  6. PL/SQL工具连接ORALCE数据库的方法
  7. NSString字符串
  8. 遍历HashMap的四种方法
  9. redis主从配置及主从切换 转
  10. js 神代码
  11. ASP.NET 获取来源网站的网址,获取上一网页的网址,获取来源网页的URL,获取上一网页的URL
  12. Keil C51 Data Overlaying
  13. hdu 4115 石头剪子布(2-sat问题)
  14. POJ 1611 The Suspects(简单并查集)
  15. 位图文件(BMP)格式以及Linux下C程序实现(转)
  16. H5前端性能测试总结
  17. JVM垃圾回收器
  18. 前端页面调用Spring boot接口发生的跨域问题
  19. tensorflow 1.9 ,bazel 0.15.0,源码编ERROR, Skipping, '//tensorflow/tools/pip_package:build_pip_package',error loading packageCuda Configuration Error, Cannot find libdevice.10.bc under /usr/local/cuda-8.0
  20. 关于CLOS架构的举例 网络级 设备级 FATTREE网络 网络级CLOS 以及CLOS涉及的调度算法RR

热门文章

  1. kmp变形,带通配符的kmp——华科校赛E 好题
  2. 判断MDI窗体的子窗体是否存在
  3. 三模数NTT模板
  4. CentOS7的mysql5.7-rpm.bundle方式安装
  5. react 高阶组件之小学版
  6. Web开发-Servlet&HTTP&Request
  7. 4_5.springboot2.x之Web开发RestfulCRUD操作
  8. 【LGP4714】「数学」约数个数和
  9. DIV常用属性大全自己整理
  10. Amazon AWS