【C语言】函数指针及其应用

article/2025/9/7 20:35:30

目录

1.1  函数指针的概念和应用

1.2  赋值与内存模型

1.3  调用方式与注意事项

二、函数指针的使用

2.1  函数指针的定义和访问

2.2  动态调度:用户输入驱动函数执行

2.3  函数指针数组进阶应用

2.4  函数作为参数的高阶抽象

三、回调函数

3.1  指针函数vs函数指针

3.2  指针函数应用

3.3  回调函数机制解析

3.4  消息循环


函数指针是C语言中指向函数的指针变量,其本质是存储函数入口地址的指针。与普通指针不同,函数指针指向的是代码段中的可执行指令,而非数据存储区域。

1.1  函数指针的概念和应用

·核心概念

函数指针的类型由函数的返回值类型和参数列表共同决定。

例如:

input (*ptr)(int, char) 

表示ptr是一个指向返回值为int、参数为 (int, char) 的函数的指针。

·应用

  • 动态函数调用:根据运行时条件选择执行不同函数
  • 回调机制:实现框架与业务代码的解耦
  • 算法通用化:如自定义排序函数的比较逻辑

1.2  赋值与内存模型

  • 示例
int add(int a, int b){ return a+b; } //两数之和
int sub(int a, int b){ return a-b; } //两数之差
  • 函数指针赋值 
//函数指针赋值
int (*ptr)(int, int) = add; //直接赋值函数名(隐式取地址)
ptr = ⊂ //显式取地址(等价于sub)

·内存本质:函数指针存储的是函数在内存中的起始地址(add与&add等价),该地址指向函数的机器码起始位置。 

1.3  调用方式与注意事项

int result1 = ptr(3,5);
int result2 = (*ptr)(3,5);

⚠️注意事项 

  • 调用前必须确保指针已正确指向有效函数
  • 参数类型、个数与指针声明完全匹配
  • 避免指向局部函数或已释放的函数(如动态链接库卸载后的函数)

二、函数指针的使用

2.1  函数指针的定义和访问

//使用typedef简化声明
typedef int (*Func)(int, int);Func ad = add; //定义简洁
int res = ad(10,20);

·类型别名优势:

  •  代码可读性提高,明确指针用途
  • 批量修改函数签名时只需要修改一处

2.2  动态调度:用户输入驱动函数执行

·头文件

#include <stdio.h>

·定义add和sub

int add(int a,int b) { return a+b; }
int sub(int a,int b) { return a-b; }

·主函数

int main() {int x,y,choice;typedef int (*Func)(int, int);Func ads[] = {add, sub};printf("选择(0:加,1:减): ");scanf("%d",&choice);printf("输入两个数: ");scanf("%d%d",&x,&y);int result = ads[choice](x,y); // 动态调用printf("结果: %d\n",result);return 0;
}

⬇️

执行逻辑:

通过数组下标映射用户输入,实现低成本的多函数调度方案 

2.3  函数指针数组进阶应用

typedef int(*MathFunc)(int, int);MathFunc funcs[] = {add,  // 0:加法sub,  // 1:减法mul,  // 2:乘法div   // 3:除法
};//动态调用示例
int result = funs[choice](a,b);

· 优势场景 

当需要管理大量函数时,数组索引可提供O(1) 时间复杂度的快速访问。

2.4  函数作为参数的高阶抽象

// 通用排序函数(接收比较函数作为参数)
void sort(int arr[], int len, int (*cmp)(int, int)) {// 冒泡排序实现for (int i=0; i<len-1; i++) {for (int j=0; j<len-i-1; j++) {if (cmp(arr[j], arr[j+1]) > 0) {// 交换元素}}}
}// 升序比较函数
int cmp_asc(int a, int b) { return a - b; }// 降序比较函数
int cmp_desc(int a, int b) { return b - a; }// 使用示例
sort(arr, 10, cmp_asc); // 升序排序
sort(arr, 10, cmp_desc); // 降序排序

三、回调函数

3.1  指针函数vs函数指针

类型定义语法本质
指针函数int* func(int a)返回指针的函数
函数指针int(*func)(int a)指向函数的指针变量

3.2  指针函数应用

// 返回动态分配数组的指针函数
int* create_arr(int size) {int* arr = (int*)malloc(size * sizeof(int));// 初始化数组return arr;
}

3.3  回调函数机制解析

回调函数是通过函数指针实现的一种双向通信机制:

  1. 调用方定义函数原型并预留指针函数
  2. 被调用方(如库函数)在特定事件发生时调用该指针
// 模拟操作系统定时器回调
typedef void (*Callback)(int data);void set_timer(int ms, Callback cb) {// 模拟定时器逻辑while (ms > 0) { /* 延时 */ }cb(42); // 时间到达时触发回调
}// 用户自定义回调函数
void on_timer(int data) {printf("定时器触发,数据: %d\n", data);
}// 使用示例
set_timer(1000, on_timer); // 注册回调函数

3.4  消息循环

// 简化的GUI消息循环
typedef void (*MsgHandler)(int msg, void* data);void message_loop(MsgHandler handler) {while (1) {int msg = get_next_message(); // 获取消息void* data = get_message_data(msg);handler(msg, data); // 分发消息到回调函数}
}// 用户注册消息处理函数
void handle_msg(int msg, void* data) {switch (msg) {case WM_CLICK:   process_click(data); break;case WM_KEYDOWN: process_keypress(data); break;}
}// 启动消息循环
message_loop(handle_msg);

🌟个人主页🌟

👾C语言学习合集(草稿版)👾


http://www.hkcw.cn/article/tSbIaovpJt.shtml

相关文章

第十三章:预处理

预处理功能是C语言特有的功能,可以使用预处理和具有预处理的功能是C 语言和其他高级语言的区别之一。预处理程序包含许多有用的功能,如宏定义、条件编译等,使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计。 通过本章的学习,您可以: 1、掌握…

9.4 Q1|复旦大学CHARLS发文 | 老年人肌肉减少症和轻度认知障碍

1.第一段-文章基本信息 文章题目&#xff1a;Sarcopenia and mild cognitive impairment among elderly adults: The first longitudinal evidence from CHARLS 中文标题&#xff1a;老年人肌肉减少症和轻度认知障碍&#xff1a;来自CHARLS 的第一个纵向证据 发表杂志&#x…

python h5py 读取mat文件的<HDF5 object reference> 问题

我用python加载matlab的mat文件 mat文件&#xff1a; 加载方式&#xff1a; mat_file h5py.File(base_dir str(N) _nodes_dataset_snr- str(snr) _M_ str(M) .mat, r) Signals mat_file["Signals"][()] Tp mat_file["Tp"][()] Tp_list mat_fil…

【数据结构】图论核心算法解析:深度优先搜索(DFS)的纵深遍历与生成树实战指南​

深度优先搜索 导读&#xff1a;从广度到深度&#xff0c;探索图的遍历奥秘一、深度优先搜索二、算法思路三、算法逻辑四、算法评价五、深度优先生成树六、有向图与无向图结语&#xff1a;深潜与回溯&#xff0c;揭开图论世界的另一面 导读&#xff1a;从广度到深度&#xff0c;…

扫地机产品异物进入吸尘口堵塞异常检测方案

扫地机产品异物进入吸尘口堵塞异常的检测方案 文章目录 扫地机产品异物进入吸尘口堵塞异常的检测方案一.背景二.石头的音频异常检测的方案2.1 音频检测触发点2.1.1时间周期2.1.2根据清洁机器人清扫模式或清扫区域污渍类型,即当清扫模式为深度清洁模式 或清扫区域污渍类型为重度…

【Mini-F5265-OB开发板试用测评】RT-Thread的移植(调通串口+LED)

前言 近期&#xff0c;笔者有幸获得灵动微MM32F5265开发板的体验资格。MM32F5260搭载了arm china "Star-MC1 内核"处理器&#xff0c;拥有高性能&#xff0c;主打家电和工业等高可靠性应用领域。 总结一下&#xff0c;有以下亮点&#xff1a; 本土团队打造&#x…

MySQL8.4组复制

https://dev.mysql.com/doc/refman/8.4/en/group-replication.html 1 什么是组复制 组复制主要解决了传统异步复制主机宕机时可能造成主从节点数据不一致问题MySQL Group Replication&#xff0c;简称MGR将原有的gtid复制功能进行可增强&#xff0c;支持单主模式和多主模式组复…

【笔记】Trae+Andrioid Studio+Kotlin开发安卓WebView应用

文章目录 简介依赖步骤AS(Andriod Studio)创建项目AS创建虚拟机TRAE CN 修改项目新增按键捕获功能 新增WebViewWebView加载本地资源在按键回调中向WebView注入JS代码 最终关键代码吐槽 简介 使用Trae配合Andriod Studio开发一个内嵌WebView的安卓应用, 在WebView中加载本地资源…

kibana解析Excel文件,生成mapping es导入Excel

一、Excel转为CSV格式 在线免费网站&#xff1a;EXCEL转CSV - 免费在线将EXCEL文件转换成CSV (cdkm.com) 二、登录kibana 点击左边菜单栏找到Machine Learning&#xff0c; 进入后上面菜单选择Data Visualizer&#xff0c;然后上穿转好的csv格式的Excel 点击导入输入建立的m…

4d毫米波雷达开源算法4DRadarSLAM运行

1.开源代码和论文 &#xff08;1&#xff09;论文名称&#xff1a; 4DRadarSLAM: A 4D Imaging Radar SLAM System for Large-scale Environments based on Pose Graph Optimization &#xff08;2&#xff09;开源代码国内下载地址 https://gitcode.com/gh_mirrors/4d/4DRada…

安卓手机照片在这个目录/storage/emulated/999/DCIM/Camera下的导出解决方案

这里写自定义目录标题 背景解决方案导出过程 导出的成功照片展示 背景 想导出手机的相册照片,发现部分照片无法导出 &#xff0c;原因是在文件管理根本找不到这个目录/storage/emulated/999/DCIM/ 。 照片位置截图&#xff1a; 对应的安卓手机的文件管理截图如下 发现没有…

C++进阶--C++11(04)

文章目录 C进阶--C11&#xff08;04&#xff09;lambdalambda表达式语法捕捉列表lambda的应用lambda的原理 包装器functionbind 总结结语 很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 今天我们进一步c…

动态设置微信小程序页面标题(navigationBarTitleText属性)

前言&#xff1a; 最近在公司进行小程序研发的时候&#xff0c;产品给出了一个动态加载页面标题的需求&#xff0c;经过调研之后将结果在这里与各位伙伴进行分享。 代码展示&#xff1a; 在.json文件中进行初始配置&#xff1a; { "usingComponents": {}, &q…

PostgreSQL数据库配置SSL操作说明书

背景&#xff1a; 因为postgresql或者mysql目前通过docker安装&#xff0c;只需要输入主机IP、用户名、密码即可访问成功&#xff0c;这样其实是不安全的&#xff0c;可能会通过一些手段获取到用户名密码导致数据被窃取。而ES、kafka等也是通过用户名/密码方式连接&#xff0c;…

基于python 将图像上同一行距离相近的矩形框融合

import os import cv2 import numpy as npdef get_files(path):""" 获取指定路径下所有文件名称 """files []for filename in os.listdir(path):if os.path.isfile(os.path.join(path, filename)):files.append(filename)return filesdef split…

拉取gitlab项目

一、下载nvm管理node 先下载配置好nvm,再用nvm下载node 下载链接&#xff1a;开始 下载nvm - nvm中文官网 情况&#xff1a;npm i 下载依赖缓慢&#xff0c;可能是node版本不对&#xff0c;可能node版本太高 可能得问题&#xff1a;使用nvm 下载低版本的node时&#xff0c;…

Opencv4 c++ 自用笔记 01 Mat类

Mat类 Mat类用来保存矩阵类型的数据&#xff0c;包括向量、矩阵、灰度、通道数。主要分为两部分&#xff0c;矩阵头和矩阵指针。 &#xff08;单通道为灰度图像&#xff0c;3通道或4通道为彩色图像&#xff09; 矩阵头中包含矩阵形状、存储方法、地址、引用次数等。矩阵指针…

Linux `|` 管道符与 `grep` 命令深度解析与高阶应用指南

Linux `|` 管道符与 `grep` 命令深度解析与高阶应用指南 一、核心机制深度解析1. 管道符 `|` 的底层原理2. grep 的匹配引擎二、高阶组合应用技巧1. 多级过滤管道2. 实时监控与告警3. 结构化数据处理三、企业级应用场景1. 安全审计系统2. 性能监控告警3. 日志关联分析四、性能优…

STP配置

由于我们演示的是STP 但是华为交换机默认的都是MSTP所以要换到STP以下是方法 STP mode &#xff1f; 查看模式 STP mode stp 选择stp 换好了后配置交换机优先级 [SWA]stp priority 4096 Apr 15 2013 16:15:33-08:00 SWA DS/4/DATASYNC_CFGCHANGE:OID 1.3.6.1.4.1.2011.5…

CentOS_7.9 2U物理服务器上部署系统简易操作步骤

近期单位网站革新&#xff0c;鉴于安全加固&#xff0c;计划将原有Windows环境更新到Linux-CentOS 7.9&#xff0c;这版本也没的说&#xff08;绝&#xff09;了&#xff08;版&#xff09;官方停止更新&#xff0c;但无论如何还是被sisi的牵挂着这一大批人&#xff0c;毕竟从接…