服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - c++函数名指针和函数指针

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

2022-09-20 21:08wei2023 C/C++

这篇文章主要介绍了c++函数名指针和函数指针,函数指针和数据类似,C++当中函数也有地址,函数的地址是存储函数机器语言代码的内存地址。我们可以将另外一个函数的地址作为参数传入函数,从而实现函数的灵活调用,下面详细

前言

我们先来看一下函数指针式如何定义的,假如我们有一个函数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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
void fun(int a)
{
 
}
 
int main()
{
    cout<<fun<<endl;
    cout<<*fun<<endl;
    cout<<&fun<<endl;
    cout<<*****fun<<endl;
}

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

例 2

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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赋值之后大家一样理解就行了。

代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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的时候他会转换成函数指针而实际上这个指针只是一个临时值而临时值是没有实际存放的内存地址的所以也就无法继续取地址了!

到此这篇关于c++函数名指针和函数指针的文章就介绍到这了,更多相关c++函数名指针和函数指针内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_31329259/article/details/113767023

延伸 · 阅读

精彩推荐
  • C/C++C++11/14的新特性(更简洁)

    C++11/14的新特性(更简洁)

    这篇文章主要介绍了C++11/14的新特性(更简洁),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    小念之歌5812021-07-19
  • C/C++C++初始化列表学习

    C++初始化列表学习

    在C++中,struct和class的唯一区别是默认的克访问性不同,而这里我们不考虑访问性的问题,所以下面的代码都以struct来演示...

    C++教程网10112020-12-25
  • C/C++北邮考研复试C语言上机题目精选

    北邮考研复试C语言上机题目精选

    这篇文章主要介绍了北邮考研复试C语言上机题目精选,摘自2010年北邮CS的复试,需要的朋友可以参考下...

    小一的专栏12442021-03-07
  • C/C++C++中实现矩阵的加法和乘法实例

    C++中实现矩阵的加法和乘法实例

    这篇文章主要介绍了C++中实现矩阵的加法和乘法实例的相关资料,需要的朋友可以参考下...

    不见x的心5692021-05-06
  • C/C++C++实现LeetCode(123.买股票的最佳时间之三)

    C++实现LeetCode(123.买股票的最佳时间之三)

    这篇文章主要介绍了C++实现LeetCode(123.买股票的最佳时间之三),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参...

    Grandyang10192021-12-03
  • C/C++C语言实现冒泡排序的思路以及过程

    C语言实现冒泡排序的思路以及过程

    冒泡排序是最简单的排序方法,理解起来容易。虽然它的计算步骤比较多,不是最快的,但它是最基本的,初学者一定要掌握。本文给大家介绍的非常详细...

    飞人01_0110062022-01-06
  • C/C++c++调用实现yolov5转onnx介绍

    c++调用实现yolov5转onnx介绍

    大家好,本篇文章主要讲的是c++调用实现yolov5转onnx介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    小军军军军军军10572022-07-22
  • C/C++C++通过TerminateProess结束进程实例

    C++通过TerminateProess结束进程实例

    这篇文章主要介绍了C++通过TerminateProess结束进程实例,是Windows应用程序设计中非常实用的技巧,需要的朋友可以参考下...

    C++教程网8392021-02-06