C++ extern “C”的作用详解


Reference:

  1. extern “C”的作用详解

extern "c" 的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上 extern “c” 后,会指示编译器这部分的代码按C语言,而不是C++的方式进行编译。

由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。

这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的。为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而 extern “c” 就是其中的一个策略。

这个功能主要用在以下情况:

  1. C++代码调用C语言代码;
  2. 在C++的头文件中使用;
  3. 在多人协同开发时,有的人比较擅长C语言,而有的比较擅长C++,这样的情况下也会有用到。

1.示例

有moduleA、moduleB两个模块,B调用A中的代码,其中A是用C语言实现的,而B是利用C++实现的,下面给出一种实现方法:

//moduleA头文件
#ifndef __MODULE_A_H //对于模块A来说,这个宏是为了防止头文件的重复引用
#define __MODULE_A_H
int fun(int, int);
#endif
 
//moduleA实现文件moduleA.c //模块A的实现部分并没有改变
#include"moduleA"
int fun(int a, int b)
{
return a+b;
}
 
//moduleB头文件
#idndef __MODULE_B_H //很明显这一部分也是为了防止重复引用
#define __MODULE_B_H
#ifdef __cplusplus 
//这一部分就是告诉编译器,如果定义了__cplusplus(即如果是cpp文件----cpp文件默认定义了该宏),
// 则采用C语言方式进行编译
extern "C"{ 
#include"moduleA.h"
#endif//其他代码
 
#ifdef __cplusplus
}
#endif
#endif
 
//moduleB实现文件 moduleB.cpp //B模块的实现也没有改变,只是头文件的设计变化了
#include"moduleB.h"
int main()
{
  cout<<fun(2,3)<<endl;
}

2. 补充说明-C、C++编译器

由于 C 和 C++ 编译器对函数的编译处理是不完全相同的,尤其对于 C++ 来说,支持函数的重载,编译后的函数一般是以函数名和形参类型来命名的。

例如函数 void fun(int, int) 编译后的可能是 _fun_int_int----不同编译器可能不同,但都采用了相似机制,用函数名和参数类型来命名编译后的函数名;而C语言没有类似的重载机制,一般是利用函数名来指明编译后的函数名的,对应上面的函数可能会是 _fun 这样的名字。

因此,如果不加 extern “c”,在链接阶段,链接器会从 moduleA 生成的目标文件 moduleA.obj 中找 _fun_int_int 这样的符号,显然这是不可能找到的,因为 fun() 函数被编译成了_fun 的符号,因此会出现链接错误

如下面面试题:为什么标准头文件都有类似的结构?

#ifndef __INCvxWorksh /*防止该头文件被重复引用*/
#define __INCvxWorksh
#ifdef __cplusplus             //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
extern "C"{
#endif

/*…*/

#ifdef __cplusplus
}

#endif
#endif /*end of __INCvxWorksh*/

3. extern "C"使用要点

  1. 可以是如下的单一语句:

extern “C” double sqrt(double);

  1. 可以是复合语句, 相当于复合语句中的声明都加了 extern “C”:

extern “C”
{
      double sqrt(double);
      int min(int, int);
}

  1. 可以包含头文件,相当于头文件中的声明都加了extern “C” (不建议这样写,会有嵌套可能)

extern “C”
{
      #include <cmath>
}

  • 不可以将 extern “C” 添加在函数内部;
  • 如果函数有多个声明,可以都加 extern “C”, 也可以只出现在第一次声明中,后面的声明会接受第一个链接指示符的规则。
  • 22
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
extern关键字在C语言中有多种用法。 第一种用法是在变量的声明中使用extern关键字,表示该变量在其他源文件中定义。例如,extern const char Buffer[];表示Buffer变量在其他文件中定义,并可以在当前文件中使用。 第二种用法是在函数的声明中使用extern关键字,表示该函数可能在其他源文件中定义。例如,extern int f();表示f函数可能在其他文件中定义,并可以在当前文件中使用。 第三种用法是在C++中使用extern "C"来指定函数的链接方式。这是为了解决C++函数重载带来的函数名和参数不同导致链接错误的问题。通过extern "C"修饰函数,告诉编译器保持函数名称不变,不生成用于链接的中间函数名。这通常在C++代码中与C函数交互时使用。 总而言之,extern关键字在C语言中用于声明变量和函数的链接方式,以及在C++中用于修饰函数以保持函数名称不变。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++全局变量的定义和声明](https://blog.csdn.net/webzhuce/article/details/38899635)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C/C++extern关键字详解](https://blog.csdn.net/weixin_38218095/article/details/96473556)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值