学了就忘,忘了再学。有时感觉自己几乎就是一个跳梁小丑。没有办法,只好多记些笔记。

本文版权归作者和博客园共有

FROM: http://www.cnblogs.com/graphics/archive/2010/12/24/1916343.html

经常看到如下代码:

#ifdef _cplusplus

extern "C" {

#endif

#include "XXX.h"

#ifdef _cplusplus

}

#endif

解释:

extern "C"的作用是,告诉C++编译器,下面的代码按照C的方式进行编译,说白了,不要对这些函数进行名字重整(function name mangling)。通常在C++程序中使用C函数或者模块时,需要用到这个功能。

原因:

C++为了支持函数重载,将编译后的函数名做了重整(mangled name),比如下面的函数

int add(int a, int b) ;

在C中编译完的名字就是add,而在C++中,编译完就变成了add_int_int(举例而已,实际因编译器而异),这样在函数名字后面加上参数的类型,就可以区分不同的重载函数了,比如还有另一个函数

float add(float a, float b) ;

在C++中,它会被编译成add_float_float,这就是C++区分重载函数的机制

可是问题也随之而来

C++进行名字重整,而C不进行重整。当C++程序引用C的函数时,它会按照重整后的名字去目标文件(.obj)中去寻找对应的函数,而目标文件中存放的却是C版本的函数,名字对不上,所以根本找不到!

怎么办呢?

这就是extern “C” 存在的一个原因:

它告诉C++,包含在extern “C”{ //…}块中的东西是C版本的,你编译的时候不要进行名字重整,否则你链接的时候就无法找到我!

于是上面的代码也就不难理解了,光说不练是扯淡,上代码

我们简单的定义一个C头文件和实现文件,只包含一个add函数

CClass.h 内容如下

#ifndef __CClass_H__

#define __CClass_H__

extern int add(int a, int b) ;

#endif // end __CClass_H__

CClass.c 内容如下

#include "CClass.h"

int add(int a, int b)

{

return a + b ;

}

下面我们用一个C++程序来引用这个C文件

main.cpp 内容如下

#define _cplusplus // 为了测试,强加一句

#ifdef _cplusplus

extern "C" {

#endif

#include "CClass.h"

#ifdef _cplusplus

}

#endif

#include <iostream>

using namespace std ;

int main(void)

{

int result = add(1, 2) ;

cout << result << endl ;

system("pause") ;

return 0 ;

}

如果没有#include <iostream>之前那些代码而只是仅仅包含

#include "CClass.h"一句

你就会得到下面的错误

error LNK2019:unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _main

显然这是一个链接错误,因为找不到对应的函数定义

当然你也可以简写成下面的形式,直接在extern “C”块中包含你想调用的函数

extern "C"

{

int add(int a, int b) ;

};

#include <iostream>

using namespace std ;

int main(void)

{

int result = add(1, 2) ;

cout << result << endl ;

system("pause") ;

return 0 ;

}

这在C++程序中是没有问题的,但是如果是在C程序中,则会出现编译错误,因为C中不允许extern “C”出现

另一个需要extern “C”的场合是当C程序调用C++的东西时

按照如下步骤做即可

1. 在C++的.h文件中用extern “C”{}声明将被C程序使用的函数

2. 在C++的.cpp文件中实现上面的函数

3. 在.c文件中用extern声明要使用的C++函数

4. 使用即可

注意:切不可在.c文件中包含C++的.h文件,那样编译无法通过

上代码:

CPPClass.h中声明add函数

#ifndef __CPPClass_H__

#define __CPPClass_H__

extern "C"

{

int add(int a, int b) ;

};

#endif // end __CPPClass_H__

CPPClass.cpp实现add函数

#include "CPPClass.h"

int add(int a, int b)

{

return a + b ;

}

main.c 内容如下

#include <stdio.h>

//#include "CPPClass.h" // 不要包含头文件,否则编译不过

extern int add(int a, int b) ; // 只需显示声明要调用的函数即可

int main(void)

{

int result = add(1, 2) ; //使用函数

printf("%d", result) ;

return 0 ;

}

extern “C”总结相关推荐

  1. C++ 笔记(05)— 变量(变量定义、声明、初始化、extern关键字、变量之间转换)

    1. 变量定义 变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储.变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示: type variable_list; ...

  2. C++中extern使用

    C++中extern是指全局的意思.它一般有两个方面的用途: 1.声明变量 首先说一下声明和定义的区别: ①变量的定义:用于为变量分配存储空间,还可以为变量指定初始值.在一个程序中,变量有且仅有一个定 ...

  3. extern数组与extern指针

    数组名代表了存放该数组的那块内存,它是这块内存的首地址.这就说明了数组名 是一个地址,而且,还是一个不可修改的常量,完整地说,就是一个地址常量.数组名 跟枚举常量一样,都属于符号常量.数组名 这个符号 ...

  4. C语言extern关键字定义外部变量--Redis源码extern使用

    在Redis2.8中有networking.c,这个文件没有networking.h networking.c首先引入redis.h这个头文件 #include "redis.h" ...

  5. C++中extern的使用

    在C++中,extern主要有两个作用:(1).extern声明一个变量或函数:(2).extern与"C"一起连用,用于链接指定.关于extern "C"的使 ...

  6. C++中extern C的使用

    C++程序有时需要调用其它语言编写的函数,最常见的是调用C语言编写的函数.像所有其它名字一样,其它语言中的函数名字也必须在C++中进行声明,并且该声明必须指定返回类型和形参列表.对于其它语言编写的函数 ...

  7. C/C++中inline/static inline/extern inline的区别及使用

    引入内联函数的目的是为了解决程序中函数调用的效率问题,也是用内联函数取代带参宏定义(函数传参比宏更加方便易用) inline关键字用来定义一个类的内联函数. 在类体中和类体外定义成员函数是有区别的:在 ...

  8. C++项目中的extern C {}

    2010-07-10 19:45 by 吴秦, 92864 阅读, 22 评论, 收藏, 编辑 引言 在用C++的项目源码中,经常会不可避免的会看到下面的代码: ? 1 2 3 4 5 6 7 8 9 ...

  9. 浅谈C/C++中的static和extern关键字

    一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数.在不同的情况下static的作用不尽相同. (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的 ...

  10. extern “C“

    1. 说明 被 extern 限定的函数或变量是 extern 类型的 被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和连接的 extern "C&q ...

最新文章

  1. 企业并不怕尝新 业务变革的技术们
  2. .net中的socket异步通信实现--客户端代码
  3. Java学习笔记#数组的初始化方式
  4. C#中的Dictionary字典类介绍(转载)
  5. 需求、需求工程与需求工程师 — 1.定义、作用
  6. 小学生眼里的飞鸽传书
  7. 自然语言处理 —— 困惑度
  8. webSphere报错:Error 500: javax.servlet.ServletException: SRVE0207E: Uncaught initialization
  9. bzoj 4561: [JLoi2016]圆的异或并(扫描线+set)
  10. kafka处理大数据包
  11. 《企业IT架构转型之道》阿里巴巴中台战略思想和架构实战-书摘整理
  12. 轮询、长轮询、长连接、websocket
  13. xp计算机找不到音量调节,winxp系统电脑音量无法调节不能调节声音的恢复方案...
  14. 动态平衡网格交易_网格交易 套利:期货经典书籍
  15. 浙江电信张涛:天翼阅读未来将收费 资费采用包月形
  16. swift语言前景_swift语言从天而降,作为ios程序猿,我们如果面对?
  17. excel 链接sql server数据库,并使用sql语句导出自己想要的数据
  18. CS61A fa2021 Composing Programs 2.7 Object Abstraction 对象抽象
  19. 八大口碑速溶咖啡品牌盘点
  20. QWebEngine自动添加麦克风和摄像头权限

热门文章

  1. python 操作redis,存取为字节格式,避免转码加
  2. H3C FTP配置示例
  3. java_day19_MVC和配置文件
  4. Mysql5.7.20使用group by查询(select *)时出现错误--修改sql mode
  5. java中的内部类总结
  6. dyld: Library not loaded: @rpath/libswiftCore.dylib 解决方法
  7. 为什么“三次握手,四次挥手”?
  8. Discretized Streams: An Efficient and Fault-Tolerant Model for Stream Processing on Large Clusters
  9. 张小娴的文章,喜欢的,贴来存档
  10. 检测字符串包含emoji表情