extern "C" 与函数重载机制

来源:互联网 发布:c语言控制台编程 编辑:程序博客网 时间:2024/06/09 21:07

★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重命名结束。

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


0 0
原创粉丝点击