关于 extern "C"

当这个世界还只有C的时候,是不需要extern "C"的。

但是,当C++出现之后,有时候,我们就需要extern "C"了。

那究竟是在什么样的情况下,我们需要用extern "C"呢?

有人说,是为了C能够调用C++,有人说是为了在C++中能调用C的库函数。是不是把你弄糊涂了?

 

先说说extern "C"是啥作用吧。

extern "C" 是告诉C++编译器,这个函数是完全兼容C的,不包含C++有而C中没有的特性的。并且告诉编译器,在生成目标文件的时候,使用C的方式生成函数名。

上面这句话有两个重点,

第一是 extern "C" 只有 C++编译器认得,C编译器是不认识的。

第二是 用C的方式生成函数名。什么叫 "用C的方式生成函数名"? C++编译器和C编译器生成函数名的方式是不同的。因为C++要支持函数重载,所以C++编译器在生成函数名的时候会把函数参数的类型加在函数名中。而C编译器就比较简单,直接在函数名字前加一个下划线搞定。

比如 void foo( int x ); 这样的函数

C编译器编译出来在符号库中的名字是_foo,而C++编译器编译出来在符号库中的名字可能是 _foo_int 这样的。

 

 

那么使用 extern "C" 有什么意义呢?

我觉得 ”为了C++中能调用C的库函数“ 这样的说法是正确的。

为什么?

考虑下面的情况,你有一个C实现的库,并用C编译器编译生成库文件。

假设这个库里有一个函数为 void foo( int );

在C++的某个类中,你要用这个foo函数,你在C++源文件中用

extern void foo( int );

引入。

这样在链接的时候出错了。

因为C++编译器在编译C++源文件的时候,认为void foo( int ); 在符号表中应该是

_foo_int 这个样子的。而在链接的时候找不到_foo_int,只有_foo。所以链接出错了。

 

怎么解决呢?

extern void foo( int );

改成

extern "C" void foo( int );

就行啦。

 

如果是直接include C的头文件的,那可以这样

extern "C" {

#include "HeaderOfC.h"

}

 

这样C++编译器就知道,这个foo是C的函数,生成名字的时候不需要带参数。这样链接的时候就没问题啦。

 

 

那么在今天,我们写一个C的库的时候,当然存在我们的库被C++的程序所使用的可能性。

我们不希望在C++的源码中引用我们的头文件的时候还要

extern "C" {

#include "yourlib.h"

}

这么麻烦。

 

所以我们在写C的库的头文件的时候主动的加上了 extern "C"。

但这里有一个问题,因为C编译器不认识extern "C"啊,所以就有了

宏 __cplusplus

对于C编译器,没有定义这个宏,而C++编译器定义了这个宏。

 

所以,C语言的头文件的标准写法是

#ifndef XXX_XXX_H

#define XXX_XXX_H

 

#ifdef __cplusplus

extern "C" {

#endif

 

 

/* 这里是头文件的内容 */

 

 

#ifdef __cplusplus

}

#endif

 

#endif

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值