(函数指针) 指向函数的指针

函数指针- 指向函数的指针

  • 函数指针的声明和使用
  • 通过函数指针调用函数
  • 函数指针做参数
  • 函数指针数组

函数指针的声明和使用

函数指针的声明格式:
返回值类型 (*函数指针名)(参数列表);

其中:

  • *函数指针名 表示函数指针的名称
  • 返回值类型 则表示该指针所指向的函数的返回值类型
  • 参数列表 则表示该指针所指向的函数的参数列表。

例如:

int func(int x,int y); //声明一个函数
fp=func;//将函数func的首地址给fp指针
int (*fp)(int, int); //声明一个函数指针

表示一个指向返回值类型为 int,参数类型为两个 int 的函数的函数指针。

  • 举例:func加法
// 声明一个函数
int func(int x, int y) {
    return x + y;
}

int main() {
    // 声明一个函数指针
    int (*fp)(int, int);

    // 将函数的首地址赋给函数指针
    fp = func;

    // 通过函数指针调用函数
    int result = (*fp)(1, 2);    // result = 3

    return 0;
}

在这段代码中,我们通过 fp = func; 将函数 func 的首地址赋给了函数指针 fp,然后通过 (*fp)(1, 2) 可以调用 func 函数,并将结果赋给变量 result。


通过函数指针调用函数

使用格式: (*函数指针名)(参数列表);

// 声明一个函数
int func(int x, int y) {
    return x + y;
}

int main() {
    // 声明一个函数指针
    int (*fp)(int, int);

    // 将函数的首地址赋给函数指针
    fp = func;

    // 通过函数指针调用函数
    int result = (*fp)(1, 2);    // result = 3

    return 0;
}

上面函数func我们用fp指向了它,然后调用时候使用的是(*fp)(参数列表);

  // 通过函数指针调用函数
    int result = (*fp)(1, 2);    // result = 3

函数指针做参数

函数指针作为函数参数的好处在于可以让函数接受一个函数作为输入,从而增强函数的灵活性和可重用性。通过传递不同的函数指针,可以让同 一个函数执行不同的操作,从而减少了代码的重复编写。

下面举个例子:

  • 用函数指针实现带有菜单驱动的数组排序

思路如下:

  1. 根据三种排序要求,分别定义三个排序函数
int asc(int x,int y);//升序排序,若x>y,则视为逆序返回1
int desc(int x,int y);//降序排序,若x<y,则视为逆序返回1
int AscAbs(int x,int y);//绝对值升序排序,若fabs(x)>fabs(y)则视为逆序返回1
  1. 为Sort函数添加一个指向函数的指针作为形参,sort()函数原型如下:
void Sort(int arr[],int n,int(*f)(int x,int y));

这样就定义了一个sort函数,通过调用形参指针f所指向的函数来比较二个元素的关系(是否逆序),判断是否需要交换。

  1. 在调用sort函数时,根据不同的排序要求,选择不同的比较函数作为实参,例如下面:
Sort(a,n,asc);

具体代码如下:

#include<stdio.h>
#include<math.h>

int asc(int x,int y);//升序排序,若x>y,则视为逆序返回1
int desc(int x,int y);//降序排序,若x<y,则视为逆序返回1
int AscAbs(int x,int y);//绝对值升序排序,若fabs(x)>fabs(y)则视为逆序返回1
void Sort(int arr[],int n,int(*f)(int x,int y));

int main()
{
    int a[5]={3,-4,1,5,2};
    int select;
    int n=5,i;

    //菜单
    while (1)
    {
        printf("1.升序\n");
        printf("2.降序\n");
        printf("3.按绝对值升序\n");
        printf("0.退出\n");
        printf("请做出你的选择\n");
        scanf("%d",&select);

        if(select==0)
        break;

        if(select<0&&select>3)
        printf("请输入正确的选项\n");

        //根据用户的选择,调用不同的比较函数
        switch (select)
        {
        case 1: Sort(a,n,asc);break;
        case 2: Sort(a,n,desc);break;
        case 3: Sort(a,n,AscAbs);break;
        default:
            break;
        }
        for ( i = 0; i < 5; i++)
        {
           printf("%d ",a[i]);
           printf("\n");
        }
    }
    return 0;
        
    }
    
    int asc(int x,int y)
{
    if(x>y)
        return 1;
    else
        return 0;
}

int desc(int x,int y)
{
    if(x<y)
        return 1;
    else
        return 0;
}

int AscAbs(int x,int y)
{
    if(fabs(x)>fabs(y))
        return 1;
    else
        return 0;
}

void Sort(int arr[],int n,int(*f)(int x,int y))
{
    int i,j,t;

    //冒泡排序
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-i-1;j++)
        {
            if((*f)(arr[j],arr[j+1]))//逆序返回1
            {
                t=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=t;
            }
        }
    }
}

在这里插入图片描述

函数指针数组

我们可以把函数指针作为数组元素。比如你需要完成上面类似的选择操作,那么你就可以把这些函数用函数指针数组指向

  • 格式:返回类型 (*指针数组名[数组长度])(形参列表);

类似: int (*f[])(int x, int y)={asc,desc,AscAbs};

  • 改进上面那个程序,变为函数指针数组形式
#include<stdio.h>
#include<math.h>

int asc(int x, int y);//升序排序,若x>y,则视为逆序返回1
int desc(int x, int y);//降序排序,若x<y,则视为逆序返回1
int AscAbs(int x, int y);//绝对值升序排序,若fabs(x)>fabs(y)则视为逆序返回1
void Sort(int arr[], int n, int(*f)(int x, int y));

int main()
{
    int (*f[])(int x, int y) = {asc, desc, AscAbs};
    int a[5] = {3, -4, 1, 5, 2};
    int select;
    int n = 5, i;

    //菜单
    while (1)
    {
        printf("1.升序\n");
        printf("2.降序\n");
        printf("3.按绝对值升序\n");
        printf("0.退出\n");
        printf("请做出你的选择\n");
        scanf("%d", &select);

        if (select == 0)
            break;

        if (select < 0 || select > 3)
        {
            printf("请输入正确的选项\n");
            continue;
        }

        printf("排序前: ");
        for (i = 0; i < n; i++)
        {
            printf("%d ", a[i]);
        }
        printf("\n");

        Sort(a, n, f[select - 1]);

        printf("排序后: ");
        for (i = 0; i < n; i++)
        {
            printf("%d ", a[i]);
        }
        printf("\n");
    }
    return 0;
}

int asc(int x, int y)
{
    if (x > y)
        return 1;
    else
        return 0;
}

int desc(int x, int y)
{
    if (x < y)
        return 1;
    else
        return 0;
}

int AscAbs(int x, int y)
{
    if (fabs(x) > fabs(y))
        return 1;
    else
        return 0;
}

void Sort(int arr[], int n, int(*f)(int x, int y))
{
    int i, j, t;

    //冒泡排序
    for (i = 0; i < n - 1; i++)
    {
        for (j = 0; j < n - i - 1; j++)
        {
            if ((*f)(arr[j], arr[j + 1]))//逆序返回1
            {
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
            }
        }
    }
}

在这个例子中,定义了一个函数指针数组f[],可以按照数组下标从0到2的顺序存储三个不同的函数指针。每个函数指针都是指向不同的比较函数,即asc()、desc()和AscAbs()。

在主函数中,通过菜单的形式让用户进行选择,然后调用不同的比较函数来进行排序。具体来说,根据用户的选择,索引相应的函数指针,然后调用Sort()函数来进行排序。在调用Sort()函数时,直接把函数指针作为参数传递给函数,就可以根据用户的选择来决定使用哪个比较函数进行排序。

最后,可以看到在Sort()函数中,调用了函数指针所指向的函数,因为函数指针本身并没有实现函数的功能,只是指向函数的地址。而在具体的排序过程中,需要使用到函数指针所指向的函数的功能,因此需要通过函数指针来调用相应的函数。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/9583.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

swf怎么转换成mp4格式,5个方法都很简单

swf怎么转换成mp4格式&#xff1f;各位小伙伴们有没有遇到过想要打开swf文件却需要安装flash插件的情况呢&#xff1f;其实&#xff0c;swf文件是flash软件或者animate软件导出的flash软件的专属格式&#xff0c;主要应用于动画设计领域,在网页html设计中非常常见&#xff0c;但…

(数字图像处理MATLAB+Python)第四章图像正交变换-第二节:离散余弦变换和K-L变换

文章目录一&#xff1a;离散余弦变换&#xff08;Discrete Cosine Transform&#xff0c;DCT&#xff09;&#xff08;1&#xff09;一维DCTA&#xff1a;定义B&#xff1a;实例&#xff08;2&#xff09;二维DCTA&#xff1a;定义B&#xff1a;实例C&#xff1a;程序&#xff…

UE4 几种常见的项目优化方式

1.灯光范围优化 当屏幕某一块像素被多盏灯光所影响&#xff0c;那么也会拖慢帧率&#xff0c;可以打开灯光复杂度视图进行查看&#xff0c;屏幕上越红的地方灯光复杂度越高&#xff0c;尝试降低灯光半径可以解决&#xff1a; 2.材质纹素优化 有时候我们并不知道目标模型的…

OJ练习LeetCode-118:杨辉三角

题目 118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 可以看到&#xff0c;默认的代码块中出现List<List<Integer>>为二级ArrayList&#xff0c;类似于数组中的二维数组。List<元素类型> 在List<List<Integer>>中&#xff0c;元素类型…

百度天工AIoT设备应用使能平台助力企业低成本开发

数字中国建设的顶层文件《数字中国建设整体布局规划》&#xff08;以下简称《规划》&#xff09;于近日印发&#xff0c;作为数字中国建设的重要基础&#xff0c;《规划》指出&#xff0c;要全面赋能经济社会发展&#xff0c;推动数字技术和实体经济的深度融合&#xff0c;产业…

如何将本地项目上传到Github的方法步骤

默认&#xff1a;已经安装好了git。 第一步&#xff1a;我们需要先创建一个本地的版本库&#xff08;其实也就是一个文件夹&#xff09;。 你可以直接右击新建文件夹&#xff0c;也可以右击打开Git bash命令行窗口通过命令来创建。 第二步&#xff1a;通过命令git init把这个…

chatGPT所在地区不支持怎么解决-需要下载ChatGPT吗

ChatGPT国内能下载吗 ChatGPT是基于云端的人工智能交互服务&#xff0c;无需下载即可使用。因此&#xff0c;您不需要在国内下载ChatGPT&#xff0c;只需要在网络环境联通的情况下&#xff0c;通过浏览器访问ChatGPT官网或合作伙伴提供的ChatGPT服务即可使用。当然&#xff0c…

怎么评价2023年第十三届MathorCup高校数学建模挑战赛?

文章目录赛题思路选题建议1 竞赛信息2 竞赛时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; 选题建议 首先要注意&#xff0c;A、B题为研究生组可选题目&#xff0c;A…

【分享购】“消费+分享”的新型聚合生态模式

“分享购”是一个以创新的商业模式整合流量与资源&#xff0c;实现整个生态布局的应用。结合了CPS资源、商城、礼包、异业联盟/O2等应用&#xff0c;可实现“消费分享”的新型聚合生态模式。 分享购模式所采用的五五复制的会员裂变制度是这个模式的核心亮点。 用户通过平台用户…

【Python学习笔记】4. Python大数据编程入门

4. Python大数据编程入门4.1 Python操作MySQL4.2 Spark与PySpark4.2.1 PySpark基础4.2.2 数据输入4.2.2.1 Python数据容器转换为RDD对象4.2.2.2 读取文本文件得到RDD对象4.2.3 数据计算4.2.3.1 map算子4.2.3.2 flatMap算子4.2.3.3 reduceByKey算子4.2.3.4 案例&#xff1a;单词…

亚马逊云科技云创计划,打造创新创业生态系统

在充满着不确定性的2022年&#xff0c;电子消费市场一片哀鸿遍野&#xff0c;智能家居行业却如同逆水行舟&#xff0c;显示出稳健的发展之势&#xff0c;宣告着智能家居时代已来。在2023年3月24日举办的“智能家居&#xff0c;出海闭门会”上&#xff0c;为进一步发挥产业带潜力…

zabbix自动发现和自动注册部署

目录 zabbix自动发现 确保客户端上的zabbix-agent2服务状态正常 在web页面删除原有的客户端主机 在服务端和客户端上配置 hosts 解析 在 Web 页面配置自动发现 zabbix自动注册 环境准备 修改 zabbix-agent2 配置文件 在 Web 页面配置自动注册 zabbix自动发现 对于agen…

Python 进阶指南(编程轻松进阶):七、编程术语

原文&#xff1a;http://inventwithpython.com/beyond/chapter7.html 在 XKCD 漫画《飞人五号》&#xff08;xkcd.com/1133&#xff09;中&#xff0c;网络漫画的艺术家兰道尔门罗只用了 1000 个最常见的英语单词&#xff0c;就创作出了土星五号火箭的技术示意图。这部漫画把所…

python学习之合并多张图片转成mp4视频代码实现

文章目录前言一、需要调入的模块1、imageio模块2、Image 模块二、实现合并多张图片转成 mp4 视频三、优化改进一下总结前言 随着现代科技飞速发展和人们提升视觉上体验&#xff0c;利用图片生成视频的方法&#xff0c;确实为工作或者提升生活体验感做了很多成功案例&#xff1…

vue实现好看的相册、图片网站

目录 一、效果图 1.项目访问地址 2.画虫官方效果图&#xff1a; 3.作者实现的效果图&#xff1a; 二、代码实现 1.项目结构截图 2.路由配置代码&#xff1a; 3. 头部底部主页面内容显示容器的代码 4.首页&#xff0c;即标签页的代码 三、项目启动说明 四、总结 一、…

Talk预告 | 浙江大学特聘研究员廖依伊:面向自动驾驶仿真平台的神经渲染

本期为TechBeat人工智能社区第477期线上Talk&#xff01; 北京时间3月1日(周三)20:00&#xff0c;浙江大学信电学院特聘研究员——廖依伊的Talk将准时在TechBeat人工智能社区开播&#xff01; 她与大家分享的主题是: “面向自动驾驶仿真平台的神经渲染”&#xff0c;届时将探…

Vue.js 2.0 实例

构造器 每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的&#xff1a; var vm new Vue({// 选项 }) 虽然没有完全遵循 MVVM 模式&#xff0c; Vue 的设计无疑受到了它的启发。因此在文档中经常会使用 vm 这个变量名表示 Vue 实例。 在实例化 Vue 时&…

爱智EdgerOS之深入解析在爱智应用中如何使用Socket.IO轻松实现双向通信

一、什么是 Socket.IO&#xff1f; Socket.IO 是一个基于事件通信的实时应用程序框架&#xff0c;它在即时通讯、通知和消息推送&#xff0c;实时分析等场景中有广泛的应用。Socket.IO 包括两个部分&#xff1a; 在 Server 端的模块&#xff08;JSRE 已提供了 socket.io 模块&…

密码和生物识别技术可以阻止不良行为者

网络安全漏洞是一个持续的威胁&#xff0c;而且只会越来越严重。2021 年&#xff0c;45% 的美国公司遭受了与凭证泄露相关的数据泄露&#xff0c;4200 万人因身份盗用和相关欺诈遭受了超过 500 亿美元的总价值损失&#xff0c;并且在过去五年中&#xff0c;超过5 亿个凭证和密码…