首先,作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编

译器,其声明的函数和变量可以在本模块或其它模块中使用。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,

如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用

模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块

A编译生成的目标代码中找到此函数

extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照C语言方式编译

 

和连接的,来看看C++中对类似C的函数是怎样编译的:

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中

 

的名字与c语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );

  

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字

不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”) 。

_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重

载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x,float y )编译生成的符

号是不相同的,后者为_foo_int_float。

同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变

量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也

为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

未加extern "C"声明时的连接方式

假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

int foo( int x, int y );

#endif  

在模块B中引用该函数:

// 模块B实现文件 moduleB.cpp

#include "moduleA.h"

foo(2,3);

  

实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

加extern "C"声明后的编译和连接方式 

加extern "C"声明后,模块A的头文件变为:

// 模块A头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

extern "C" int foo( int x, int y );

#endif  

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

(1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo(int x,int y),

则模块B找不到模块A中的函数;反之亦然。 (因为模块A生成的是_foo,模块B要找的是_foo_int_int)

所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是

随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还

要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):实现C++与C及其它

语言的混合编程。  

在C++程序中调用被C编译器编译后的函数为什么要加extern“C”?相关推荐

  1. 本地方法(JNI)——从java 程序中调用C函数

    [0]README 1) 本文部分文字描述 转自 core java volume 2 , 旨在理解 本地方法--从java 程序中调用C函数 的基础知识 : 2) for source code, ...

  2. 在VB应用程序中调用Excel2000

    Visual Basic简称(VB)是设计Windows应用程序强有力的开发工具,"全球绝大多数Windows应用程序都是用VB开发的": Excel是目前使用最广泛的办公应用软件 ...

  3. Linux jsp php集成环境,ImageMagick在程序中调用(linux环境,jsp,php)

    最近发现图片格式为cmyk时,图片上传浏览器不能正常显示,图片缩放会变成黑屏, 后来通过google发现imagemagick的功能很强大,安装可以采用两种方法,1)直接与php编译安装,在程序中调用 ...

  4. SQL Server 2005 - 如何在预存程序中调用另外一个预存程序

    要在一个预存程序中调用另外一个预存程序,可以使用下列两种方式之一进行调用:  <?xml:namespace prefix = o /> EXECUTE <欲执行之预存程序的名称&g ...

  5. 在Delphi程序中调用控制面板设置功能

    ====================================================== 注:本文源代码点此下载 ================================= ...

  6. 安卓程序中调用 linux 命令

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 在研究串口 jni 开发的时候,遇到了这样一段代码: Process su;su = Runtime.getRuntim ...

  7. iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,appstore,拨打电话,iTunes,iBooks )...

    在网上找到了下在记录下来以后方便用 在程序中调用系统自带的应用,比如我进入程序的时候,希望直接调用safar来打开一个网页,下面是一个简单的使用: 查看更多iPhone应用程序的调用和第三方应用程序的 ...

  8. [翻译]Kean' Blog 在一个.NET应用程序中调用AutoCAD

    程序员通常要么整合功能到AutoCAD(利用其Plug-in结构,以增加命令,用户界面,对象等),或者调用它自动完成任务.显然,这两者之间的界限已经比较模糊,但是今天我们重点介绍第二类. 用于帮助理解 ...

  9. python调用安卓相机_Android在应用程序中调用相机程序

    有时,需要在应用程序中调用其他Android上已经安装完好的应用程序, 以下是一个调用相机(com.android.camera)的demo程序: PackageInfo pi = null; try ...

最新文章

  1. aws lambda使用, aws无服务器部署应用。 aws ecr凭证获取和使用。
  2. iptables如何开放被动模式的FTP服务
  3. JS和JSP之间值传递
  4. 牛客网(剑指offer) 第九题 变态跳台阶
  5. 在腾讯云上安装mysql遇到的问题
  6. 飞信linux下载文件,OpenFetion(飞信for Linux)
  7. 两个人投票的c语言程序,设计网页投票器(二)《精通Unix下C语言编程与项目实践》之十...
  8. C# 关于MVC框架的简单实例(计算器)
  9. 【qduoj - 夏季学期创新题】矩形剖分(递归,dp)
  10. 论文浅尝 | Distant Supervision for Relation Extraction
  11. idea 保存设置 新建项目_配置、创建IntelliJ IDEA Spring MVC 项目
  12. WCF编程]WCF使用Net.tcp绑定时候出现错误:元数据包含无法解析的引用
  13. 于歆杰pdf 电路原理_buck电路原理(于歆杰 电路原理pdf)
  14. linux卸载mono,CentOS7安装Mono并保留离线安装包
  15. 使用代理服务器导致电脑无法打开网页解决办法
  16. layer弹出层内点击确认提交数据并关闭弹出层
  17. win10/win11家庭版解压缩时,出现错误代码0x80004005的解决办法
  18. 寻迹避障小车设计的ppt怎么做
  19. oracle 闩情况,理解oracle锁和oracle闩(3)TX锁和TM锁
  20. Android adb cannot connect to deamon

热门文章

  1. Suowei的ajax
  2. 2-1 年会抽奖_实现分析
  3. 第17章分布式爬虫-17-1 分布式系统简介
  4. c语言蓝色字体,C 语言输出不同颜色字体
  5. javamailsender注入失败_Springboot 之 JavaMailSender发送电子邮件
  6. C站学习导航,想用CSDN学习看我这篇就行了!
  7. 浅谈java的静态代理模式
  8. 吉大20春学期计算机系统结构在线作业一,吉大20春学期《计算机原理及系统结构》在线作业一【奥鹏百分答案】...
  9. java抓取屏幕像素,以像素为单位获取屏幕尺寸
  10. php 5.4 +iis+mysql_IIS+FastCGI+PHP5.4.4搭建PHP环境