引言

由于不同的代码互相调用起来很容易出错,甚至同一种代码但由不同的编译器编译,为实现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( , );
}

extern “C”的用法的更多相关文章

  1. C/C++之extern "C"的用法解析

    extern "C"的用法解析 http://blog.sina.com.cn/u/494a1ebc010004g5 C++中extern “C”含义深层探索 1.引言 C++语言 ...

  2. ZT extern "C"的用法解析

    extern "C"的用法解析 1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同. ...

  3. extern "C"的用法解析(转)

    原文链接:http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html   1.引言 C++语言的创建初衷是“a better C ...

  4. 【转载】extern "C"的用法解析(原博主就是抄百度百科的,不如另外一篇好)

    [说明]文章转载自Rollen Holt 的文章 http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html --------- ...

  5. [转载] extern "C"的用法解析

    本文转载自: http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html   1.引言 C++语言的创建初衷是“a better ...

  6. extern "C"的用法

    文章转自开源电子论坛:http://www.openedv.com/forum.php?mod=viewthread&tid=7986 看一些程序的时候老是有 “#ifdef __cplusp ...

  7. 转:extern "C"的用法解析

    1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同.作为一种欲与C兼容的语言, C++保留了一部分过程式 ...

  8. [C语言学习笔记二] extern 函数的用法

    extern 用来定义一个或多个变量.其后跟数据类型名和初始值.例如: extern int a =10 它与 int,long long int,double,char的本质区别,在于 extern ...

  9. 关于extern "C" 的用法

    而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误 ...

随机推荐

  1. thinkphp 判断请求类型

    判断请求类型 在很多情况下面,我们需要判断当前操作的请求类型是GET .POST .PUT或 DELETE,一方面可以针对请求类型作出不同的逻辑处理,另外一方面有些情况下面需要验证安全性,过滤不安全的 ...

  2. excel导入、下载功能

    1.excel导入.下载功能 2.首先,我们是居于maven项目进行开发引入poi,如果不是那就手动下载相应的jar包引入项目就可以了 <!-- poi --> <dependenc ...

  3. dart 异步

    使用异步有两种方法 then 或者 async/await. async/await 方法更易于理解,

  4. PyInstaller打包Python源文件为可执行程序exe

    1. 安装PyInstaller 使用命令:pip install PyInstaller时可能会由于网络的问题出现以下问题: pip._vendor.urllib3.exceptions.ReadT ...

  5. nginx源码分析-源码结构

    本文主要简单介绍nginx源码目录结构.程序编译流程.如何构建学习nginx的环境等.本文以及后续nginx源码分析文章是基于nginx当前(2009-02-27)的稳定版本0.6.35进行的分析,该 ...

  6. 【默默努力】h5-game-heroVSmonster

    先放下作者大大的项目地址:https://github.com/yangyunhe369/h5-game-heroVSmonster 然后游戏的效果为 截动图的按键与游戏按键应该冲突,我就截几张图片了 ...

  7. 便携版Mysql安装

    目录 1.安装 0.Mysql下载地址 1.解压 2.在主目录下新建data和tempData两个文件夹 3.配置环境变量 4.配置my.ini 5.安装服务(管理员模式CMD) 6.清空data文件 ...

  8. MAC地址获取,有线网卡与无线网卡、物理网卡与虚拟网卡的区分

    获取当前活跃状态的网卡MAC地址.物理地址 Wmic命令:Win32_NetworkAdapter和Win32_NetworkAdapterConfiguration. 其中cmd命令行执行: 1. ...

  9. 廖雪峰Java11多线程编程-3高级concurrent包-8CompletableFuture

    使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get() ...

  10. 实现Linux下不间断聊天和退出处理

    实现Linux下不间断聊天和退出处理