亲宝软件园·资讯

展开

c++函数名指针和函数指针

wei2023 人气:2

前言

我们先来看一下函数指针式如何定义的,假如我们有一个函数int fun(int){…};那么他对应的函数指针写法就应该是int (*p)(int);然后再对他进行赋值,即p=fun;之后你就可以在接下来的地方按p作为函数名来调用它用起来完全和fun一样。(注意这里的p指针并不是只能接受fun这个函数名,任何返回值是int,参数只有一个int的函数都可以把函数名赋给p)

首先说一下C/C++在创建一个变量的时候比如int a;相应的在内存就会分配一个4个字节(根据不同机器可能不同)空间来存放这个int变量,而假设这4个字节的起始地址是0XFF0A,那么实际上就存在一种变量名和内存地址的映射,即a可以看做是一个标示符,他只是代表着0XFF0A这个地址,在程序中你对a进行的操作实际上也就是对内存中以0XFF0A为首地址的4个字节的操作,特别是如果对a进行取地址操作也就是&a实际上就是返回0XFF0A这个地址值,实际上你可以看成就是返回一个指向这个地址的指针(如果你觉的不能理解,就当我没说吧).同理对于我们在程序中创建的函数,他是保存在程序中的单独区域的,而我们调用它们就像使用变量一样需要一个地址来唯一的指向它,所以每个函数都需要一个地址来唯一标识自己(也就是我们常说的入口地址),就像上面的a对应0XFF0A,那么假设我们定义了一个int fun(int){};函数的入口地址是0XAAEE,则fun也就是函数名他会映射0XAAEE,和上面的int变量a一样如果对它进行取地址&fun的话就会返回0XAAEE,实际上fun也是一种类型,就当它是函数名类型好了,只要记住函数名本身并不是一个指针类型就可以了。

在调用函数的时候有函数名就够了,比如fun(2);不要以为只要有函数名就能调用函数了,其实这只是写法上的一个迷惑点,而编译器在编译的时候一律都会进行所谓的"Function-to-pointer conversion",也就是把函数名隐式转换成函数指针类型,也就是要通过函数指针来调用函数,所以如果你在调用函数的时候写成(&fun)(2)也是一样能工作的,因为&fun实际上就是返回一个函数指针,参照上一段中&a的例子,只是这种写法很不常见,即使你不显式的写出&的话编译器也会隐式的进行转换,注意&fun左右的括号必须有,这是因为运算符优先级的问题。

其实即使写成(fun)(2)也是可以正常运行的,这是因为当编译器看到fun的时候发现它前面没有&也就是没有给他显示的转换成指针那么他就要隐式的转换成指针,当转换完之后发现前面又有一个这时候也就是要进行所谓的"解引用"操作,也就是到*后面里指针里取出来值,而那么值实际上也就也就是0XAAEE也就是函数名fun,这么一次隐式换然后再来一次解引用实际上相当于什么也没做,所以系统还会再进行一次隐式的"Function-to-pointer conversion",即使你写成(*******fun)(2)也会正常运行,和刚才的一个道理,只是多做了几次反复的转解操作而已,都是编译器自己完成的,不必去理会!

例 1

#include<iostream>
using namespace std;
void fun(int a)
{

}

int main()
{
    cout<<fun<<endl;
    cout<<*fun<<endl;
    cout<<&fun<<endl;
    cout<<*****fun<<endl;
}

结果输出的值都是一样的,也就是都是指向同一个函数地址的指针值。

例 2

下面再结合自己定义的函数指针来看看:

#include<iostream>
using namespace std;
int fun(int a)
{
    cout<<"fun"<<endl;
    return 0;
}

void main()
{
    int(*p)(int)=fun;
    int(*p1)(int)=*fun;
    int(*p2)(int)=&fun;
    p(1);
    p1(1);
    p2(1);
}

例 3

发现函数都能正常的运行,其实p1,p2,p和fun赋值之后大家一样理解就行了。

代码:

#include<iostream>
using namespace std;
int fun(int a)
{
    cout<<"fun"<<endl;
    return 0;
}
 
void main()
{
    int(*p)(int)=fun;
    p(1);
//  (&p)(1);   
    (*p)(1);
    (****p)(1);
}

上面的程序也都会正常的运行,只要再理解的时候把p当成只是对函数名多做了一次转换就可以了,接下来理解都一样!注意上面注释掉的哪一行是不能运行的,因为p是我们自己定义的函数指针类型,如果你对指针取地址那么将得到p这个变量本身的地址,这就不能正确调用函数了!再多说一句,其实你如果运行&&fun这个式子也是非法的,至于为什么,大家一起帮我思考思考,我个人认为当我们运行&fun的时候他会转换成函数指针而实际上这个指针只是一个临时值而临时值是没有实际存放的内存地址的所以也就无法继续取地址了!

加载全部内容

相关教程
猜你喜欢
用户评论