背景

C语言和C++有着千丝万缕的联系,C++的另外一个名称是C With Class。同时差异也是有的。

C语言不支持重载函数,因为C语言编译器编译出来的函数在符号表中的标识符即为函数名本身(这里以VisualStudio2015为例),支持重载函数意味着它们在符号表中的标识符是一样的,也就无法对他们进行区分。

C++支持重载函数,是因为C++编译器编译出来的函数在符号表中的标识符包含了参数的信息。我们知道重载函数本来就是靠参数的不同(参数个数与参数类型不同)来区分不同的函数,所以包括参数信息的标识符也就可以被分区开了。

担忧

如果C++中需要调用由C语言编译器编译出的动态库中的函数,该函数在C++中编译出的符号表中的标识带有参数信息,而其在动态库又不带参数信息,因此就会在链接时报错找不到该符号。

解决

我们可以使用extern "C"来声明使用的动态库中的函数:

extern "C" FunctionInDll();
...
// 调用FunctionInDll()

这样,C++编译器就会以C语言的方式来生成函数在符号表中的标识符,就和动态库中的标识符保持一致了。

案例

有如下VisualStudio2015动态库工程TestDll,其中包含两个文件:algorithm.halgorithm.cpp

algorithm.h

#pragma once__declspec(dllexport) int Add(int a, int b);
__declspec(dllexport) int Minus(int a, int b);
extern "C" __declspec(dllexport) int Multiply(int a, int b);
extern "C" __declspec(dllexport) int Devide(int a, int b);// 也可以使用如下的声明方式
//extern "C"
//{//  __declspec(dllexport) int Multiply(int a, int b);
//  __declspec(dllexport) int Devide(int a, int b);
//}

algorithm.cpp

#include "algorithm.h"int Add(int a, int b)
{return (a + b);
}int Minus(int a, int b)
{return (a - b);
}int Multiply(int a, int b)
{return a * b;
}int Devide(int a, int b)
{return a / b;
}

Multiply()Devide()使用extern "C"进行声明,编译工程,然后使用Dependency Walker.exe打开生成的动态库TestDll.dll:


可以看到使用和不使用extern "C"进行声明生成的标识符的明显区别。

另外,可以测试下C语言中尝试编写重载函数的实际效果:在algorithm.h中添加:

extern "C" __declspec(dllexport) int Devide(int a, int b, int c);

编译工程直接报错如下:不允许重载函数的第二个 C 链接

1>------ 已启动全部重新生成: 项目: TestDll, 配置: Debug Win32 ------
1>  algorithm.cpp
1>d:\vsproject\testdll\testdll\algorithm.h(7): error C2733: “Devide”: 不允许重载函数的第二个 C 链接
1>  d:\vsproject\testdll\testdll\algorithm.h(6): note: 参见“Devide”的声明
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

extern C的思考相关推荐

  1. 关于#define/extern/static的思考与总结

    写在前面 全局常量作为开发人员一定是一个比较熟悉的概念.全局常量的写法自然也比较多,最近在进行项目的常量重构时看到了各种各样的写法,其中宏定义占大部分,然而有很多使用宏定义是不规范的,而且宏定义只是在 ...

  2. 《c语言修炼内功之第二种境界(看代码就是内存)之关键字系列二》

    前言:这个系列内容我会深入讲解一下c语言中的重点内容,会把每一个知识点讲的更加底层些,会增强大家的c语言内功,从内存维度看代码你会有不同的理解. 这一节我主要讲一下多文件的知识,static修饰全局变 ...

  3. 嵌入在C++程序中的extern C

    1.extern的作用 extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,可以告知编译器,用extern声明的函数和变量可以在本模块或其它模块中使用. 通常,在模块的头文件中 ...

  4. 何时在C ++中使用extern

    本文翻译自:When to use extern in C++ I'm reading "Think in C++" and it just introduced the exte ...

  5. C++中extern “C”含义深层探索(zz)

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

  6. Re: Programming C/C++中extern C含义深层探索

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

  7. 揭密 extern C

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

  8. extern C的用法解析

    extern "C"的用法解析 2012-03-20 23:29 by Rollen Holt, 20231 阅读, 6 评论, 收藏, 编辑 1.引言 C++语言的创建初衷是&q ...

  9. C/C++混合编程——extern C

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

  10. C++中extern “C”含义深层探索

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

最新文章

  1. 关于亿级账户数据迁移,你应该试试这种方法...
  2. Swift3.0语言教程获取字符串长度
  3. 史陶比尔与机器人之父
  4. api接口返回动态的json格式?我太难了,尝试一下 linq to json
  5. 使用stanford nlp进行依存句法分析
  6. Java导出Highcharts需要的3个外部jar包
  7. Java类加载文章2(z)
  8. [日志]08/19/2007
  9. 027. 从从门槛和可复制性聊聊生意模式
  10. 计算机怎样同时运行多个程序的?进程相关概念介绍
  11. 医疗器械软件网络安全相关
  12. PLC脆弱性评估及相应解决方案
  13. 【中学教师资格证-教育知识与能力】简答题
  14. 结构方程模型(SEM)及其R实现
  15. 虚拟机命令里面的光标不动了怎么办_Linux 11个炫酷的终端命令!你知道几个?
  16. 成三棋、九子棋、十二子棋
  17. 《密码编码学与网络安全》复习总结
  18. excel解析工具类
  19. 蚂蚁金服如何开垦农村金融市场
  20. configure: error: C compiler cc is not found

热门文章

  1. 别了MongoDB?
  2. 《学习opencv》笔记——关于一些画图的函数
  3. 老男孩教育每日一题-第106天-MySQL如何授权用户admin:password远程访问权限
  4. jQuery直接调用asp.net后台WebMethod方法
  5. 十个必备的学习iOS开发的网站
  6. td中使用overflow:hidden; 无效解决方案
  7. 无法创建新虚拟机: 无法打开配置文件“E:\vmware\Windows7.vmx”: 拒绝访问。
  8. 1.创建一个 Slim 应用
  9. 3. 安装 phpmyadmin
  10. [Bzoj1143][CTSC2008]祭祀river