extern "C" 与函数重载机制

本文探讨了在C++中为何需要使用extern "C"声明以适应C编译器,并解释了C与C++在函数命名上的差异,导致的链接错误及解决方案。同时,介绍了函数重载机制,指出C++通过参数和返回值来决定调用哪个函数,而C语言不支持此特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

★extern "C"

先来看一下下面这道题:

在c++程序中被c编译器编译后的函数,为什么要加extern “C”?

我们来写一个简单的程序测试一下。

先写一个c++程序,简单的求两个数的和。

<span style="font-size:14px;">#include<iostream>
using namespace std;
extern int add(int ,int);
int main()
{
       int a=1;
       int b=2;
       int ret=add(1,2);
       cout<<ret<<endl;
}</span>
再在一个c文件中写add函数。

<span style="font-size:14px;">int add(int x,int y)
{
     return x+y;
}</span>
调试的时候我们就会发现这个程序在编译的时候是没有问题的,在链接的时候会提示以下错误:

1>test.obj : error LNK2019: 无法解析的外部符号 "int __cdecl add(int,int)" (?add@@YAHHH@Z),该符号在函数 _main 中被引用。

(其中_cdecl是一种调用约定。)

这是为什么呢?其实C与C++的命名方式是不同的,C语言中,函数的命名方式比较简单,在函数名前加一个_。而在C++中,函数的命名方式后面还会跟一些特殊符号和字母。

比如:

这是在C语言中add函数的命名方式:


而在C++中,add函数是这样命名的:

所以,在C++中,调用函数时编译器是下面这种命名方式C++来链接函数的,所以上面的程序是找不着对应的add函数的。这个时候,extern "C"就有用了,我们在C++文件中这样声明:

extern “C” int add(int x,int y);

就不会出现上面那种错误了。

extern “C”的作用就是告诉编译器,这是用C的方式写成的库文件,请用C的方式来链接它。C和C++对函数的处理方式是不同的.extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明。 

下面给出问题的正确答案,以做参考。

        C语言不支持函数重载,C++支持函数重载,函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型:void foo(int x,int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int _int之类的名字。C++提供了C链接交换指定符号extern"C"来解决名字匹配问题。

★函数重载机制

看下面这段代码:

<span style="font-size:14px;">#include<iostream>
using namespace std;
extern int add(int, int);
float add(float a,float b)
{
	return a + b;
}
int add(int a, int b)
{
	return a + b;
}
int main()
{
	int a = 10;
	int b = 20;
	float c = 1.0;
        float d = 2.0;
	float ret1 = add(a, b);
	int ret2 = add(a, b);
	cout << ret1<< endl;
	cout << ret2 << endl;
	return 0;
}</span>

        在调用函数时,编译器怎么知道调用哪个函数呢?这是因为函数重载机制,在程序编译时,编译器会对函数做一些处理,对函数名相同的函数进行“重命名”,如下:


我们可以看到,两个函数的名字并不是相同的,编译器在调用函数时根据参数,返回值来获取调用对象。

add@@YAHHH@Z:@@YA表示起始,HHH表示参数参数返回值,H代表int类型,M代表float类型,@Z重命名结束。

当然,不同的编译器重命名的方式也是不同的(可以查看相应的调用约定),了解在这个过程中发生了什么事就可以了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值