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

news2024/10/4 17:20:30

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

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

函数指针的声明和使用

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

其中:

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

例如:

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()函数中,调用了函数指针所指向的函数,因为函数指针本身并没有实现函数的功能,只是指向函数的地址。而在具体的排序过程中,需要使用到函数指针所指向的函数的功能,因此需要通过函数指针来调用相应的函数。


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Kubernetes】StatefulSet对象详解

文章目录简介1. StatefulSet对象的概述、作用及优点1.1 对比Deployment对象和StatefulSet对象1.2 以下是比较Deployment对象和StatefulSet对象的优缺点&#xff1a;2. StatefulSet对象的基础知识2.1 StatefulSet对象的定义2.1.1 下表为StatefulSet对象的定义及其属性&#xff1…

上岸川大网安院

一些感慨 一年多没写过啥玩意了&#xff0c;因为考研去了嘿嘿。拟录取名单已出&#xff0c;经历一年多的考研之路也可以顺利打上句号了。 我的初试成绩是380&#xff0c;政治65&#xff0c;英语81&#xff0c;数学119&#xff0c;专业课115。 回顾这一路&#xff0c;考研似乎也…

分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测

分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测 目录分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测分类效果基本介绍模型描述程序设计参考资料分类效果 基本介绍 MATLAB实现CNN-BiLSTM-Attention多输入分类预测&#xff0c;CNN-BiLSTM结合注意力机制多输…

Vue3使用Vant组件库避坑总结

文章目录前言一、问题二、解决方法三、问题出现原因总结经验教训前言 本片文章主要写了&#xff0c;Vue3开发时运用Vant UI库的一些避坑点。让有问题的小伙伴可以快速了解是为什么。也是给自己做一个记录。 一、问题 vue3版本使用vant失败&#xff0c;具体是在使用组件时失效…

IPBX系统快速部署和Freeswitch 1.10.7自动安装

IPBX系统部署文档 IPPBX系统 1.10.7版本Freeswitch &#xff0c;手机互联互通&#xff0c;SIP协议&#xff0c;分机互相拨打免费通话清晰&#xff0c;支持wifi或4G网络互相拨打电话&#xff0c;可以对接OLT设备&#xff0c;系统可以部署到本地物理机&#xff0c;也可以部署到阿…

工程质量之研发过程管理需要关注的点

一、背景 作为程序猿&#xff0c;工程质量是我们逃不开的一个话题&#xff0c;工程质量高带来的好处多多&#xff0c;我在写这篇文章的时候问了一下CHATGPT&#xff0c;就当娱乐一下&#xff0c;以下是ChatGPT的回答&#xff1a; 1、提高产品或服务的可靠性和稳定性。高质量的系…

光时域反射仪那个品牌的好用

光时域反射仪 哪个品牌好用 光时域反射仪要怎么选到合适自己的&#xff0c;这些问题 可能一直在困扰这一线的工作人员&#xff0c;下面小编就为大家一一解答下 首先光时域域反射仪是一款检测光纤线路的损耗 长度 以及 事件点的一款设备&#xff0c;在诊断 光纤线路 故障点的情…

从零开始学架构——CAP理论

CAP定理 CAP 定理&#xff08;CAP theorem&#xff09;又被称作布鲁尔定理&#xff08;Brewer’s theorem&#xff09;&#xff0c;是加州大学伯克利分校的计算机科学家埃里克布鲁尔&#xff08;Eric Brewer&#xff09;在 2000 年的 ACM PODC 上提出的一个猜想。2002 年&…

Web前端 HTML、CSS

HTML与CSSHTML、CSS思维导图一、HTML1.1、HTML基础文本标签1.2、图片、音频、视频标签1.3、超链接、表格标签1.4、布局1.5、表单标签1.6、表单项标签综合使用1.7、HTML小结二、CSS&#xff08;简介&#xff09;2.1、引入方式2.2、选择器2.3、CSS属性Web前端开发总览 Html&…

案例拆解丨ChatGPT+塔罗牌,批量起号、暴利引流,小白也能轻松月入10000+

ChatGPT 的出现&#xff0c;大大拉低了很多行业的门槛&#xff0c;比如客服、教育、翻译、自媒体……而塔罗牌占卜&#xff0c;肯定也是其中之一。 塔罗牌是一种占卜工具&#xff0c;由78张牌组成。可以用于占卜、灵性探索、个人成长和自我发现。 这是一个相对小众&#xff0c…

LinuxGUI自动化测试框架搭建(十三)-创建工具集目录tools并封装文件复制方法cpoyFile.py

(十三)-创建工具集目录tools并封装文件复制方法cpoyFile.py 1 tools的作用2 创建tools目录3 创建文件复制方法cpoyFile.py4 设计cpoyFile.py4.1 安装shutil4.2 导入模块4.3 脚本设计5 目前框架目录1 tools的作用 为了存放框架需要用到的一些常用工具或方法,比如文件复制功能…

OJ系统刷题 第九篇(难篇)

13441 - 求小数的某一位&#xff08;难题&#xff0c;二刷、三刷&#xff01;&#xff09; 时间限制 : 1 秒 内存限制 : 128 MB 分数\tfrac {a}{b}ba​化为小数后&#xff0c;小数点后第n位的数字是多少&#xff1f; 输入 三个正整数a&#xff0c;b&#xff0c;n&#xff0…

使用jni-rs实现Rust与Android代码互相调用

本篇主要是介绍如何使用jni-rs。有关jni-rs内容基于版本0.20.0&#xff0c;新版本写法有所不同。 入门用法 在Rust库交叉编译以及在Android与iOS中使用中我简单说明了jni-rs及demo代码&#xff0c;现在接着补充一些详细内容。 首先贴上之前的示例代码&#xff1a; use std:…

嘉靖王朝最大的一出闹剧和惨剧——大礼仪之争

大礼仪之争 大礼议是指发生在正德十六年&#xff08;1521年&#xff09;到嘉靖三年&#xff08;1524年&#xff09;间的一场皇统问题上的政治争论。 原因是明世宗以地方藩王入主皇位&#xff0c;为其改换父母的问题所引起&#xff0c;是明朝历史第二次小宗入大宗的事件。 “…

罗丹明荧光染料标记叶酸,FA-PEG-RB,叶酸-聚乙二醇-罗丹明;Folic acid-PEG-RB

FA-PEG-RB,叶酸-聚乙二醇-罗丹明 中文名称&#xff1a;叶酸-聚乙二醇-罗丹明 英文名称&#xff1a;FA-PEG-RB, Folic acid-PEG-RB 性状&#xff1a;粉红色固体或液体&#xff0c;取决于分子量 溶剂&#xff1a;溶于水和DMSO、DMF等常规性有机溶剂 保存条件&#xff1a;-2…

【Python】【进阶篇】二十一、Python爬虫的多线程爬虫

目录二十一、Python爬虫的多线程爬虫21.1 多线程使用流程21.2 Queue队列模型21.3 多线程爬虫案例1) 案例分析​2) 完整程序二十一、Python爬虫的多线程爬虫 网络爬虫程序是一种 IO 密集型程序&#xff0c;程序中涉及了很多网络 和 本地磁盘的 IO 操作&#xff0c;这会消耗大量…

自绘 MFC 控件 CComboBox

运行效果: 第一步:在窗口中拖拽一个CComboBox控件,设置如下属性: 类型,设置为:下拉列表包含字符串,设置为:True所有者描述,设置为:Variable 注意: 包含字符串,不设置为True,则使用GetLBText等函数无法获取到Item的text;所有者描述,设置为No,不执行DrawItem、M…

实战大数据项目

存储日志数据集&#xff08;HDFS&#xff09; 数据仓库构建&#xff08;Hive&#xff09; 数据分区表构建 数据预处理 &#xff08;Spark计算引擎&#xff09;-使用Zeppelin进行写SQL 订单指标分析 Sqoop数据导出到传统数据库&#xff08;Mysql&#xff09; Superset数据…

Vue2_02_指令

模板语法 — Vue.js (vuejs.org) 指令 (Directives) 是带有 v- 前缀的特殊 attribute 参数 一些指令能够接收一个“参数”&#xff0c;在指令名称之后以冒号表示 <a v-bind:href"url">...</a> 动态参数 可以用方括号括起来的 JavaScript 表达式作为一…

企业消费管理迈向数字化,助力员工满意度提升,解决行政·财务·采购等部门痛点 | 爱分析调研

调研&#xff1a;李进宝 撰写&#xff1a;李进宝 某市场巡视人员&#xff1a;每次出差都要垫钱&#xff0c;每月还只能报销一次&#xff0c;这不是自费上班吗&#xff1b; 某软件研发人员&#xff1a;我们每天都要加班到很晚&#xff0c;公司提供晚餐&#xff0c;但高油高盐&…