背景

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. PHP5.5.13 + Apache2.4.7安装配置流程详解
  2. 2011-2012年《软件工程》本科期末试卷
  3. 编码调试:UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xaf in position 12: illegal multibyte sequen
  4. android开发全然退出activity
  5. k均值的损失函数_K-Means算法的实现
  6. python文件命名 数字,当文件存在时,文件名中的数字递增
  7. fcc jQuery 练习
  8. 路由协议的管理距离值
  9. Shell 编程学习笔记
  10. 2003下安装Comodo pro (通用)
  11. 宏基E5572g 键盘排线插拔 拆机局部
  12. 查看计算机启动项命令,运行命令开机启动项msconfig命令简介及教程
  13. EBS功能_Oracle ERP系统借贷关系
  14. 指纹识别零日攻击的仿真器
  15. “21 天好习惯”第一期-7
  16. codevs 2905 足球晋级
  17. php仿制网站,如何仿制网站(一模一样),制造后台管理系统CMS
  18. Toncat环境变量的配置
  19. 我用20种编程语言送上新年的祝福,Happy new year!
  20. 朋友、心情与父子、亲情

热门文章

  1. 中国人工智能学会通讯——融合经济学原理的个性化推荐
  2. 信息安全产业爆发在即 十三五年均增长将达20%以上
  3. phpcmsv9 更换域名出现页面无法访问后怎么办
  4. Android 中自定义控件和属性(attr.xml,declare-styleable,TypedArray)的方法和使用 一
  5. 我今天学习的技术,明天会不会一钱不值
  6. Java咖啡馆(8)——大话面向对象(下)
  7. 3.业务架构·应用架构·数据架构实战 --- 战略驱动的业务架构设计
  8. 20.高性能MySQL --- 在MySQL上使用 Sphinx
  9. mysql 批量更新_MySQL批量更新
  10. sql中用于子查询的几个关键词 any(some是 any的别名),all,in,exists