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

目录

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.pswp.cn/bicheng/82983.shtml

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

相关文章

安装flash-attention失败的终极解决方案(WINDOWS环境)

想要看linux版本下安装问题的请走这里&#xff1a;安装flash-attention失败的终极解决方案&#xff08;LINUX环境&#xff09; 其实&#xff0c;现在的flash-attention不像 v2.3.2之前的版本&#xff0c;基本上不兼容WINDOWS环境。但是在WINDOWS环境安装总还是有那么一点不顺畅…

[C]基础16.数据在内存中的存储

博客主页&#xff1a;向不悔本篇专栏&#xff1a;[C]您的支持&#xff0c;是我的创作动力。 文章目录 0、总结1、整数在内存中的存储1.1 整数的二进制表示方法1.2 不同整数的表示方法1.3 内存中存储的是补码 2、大小端字节序和字节序判断2.1 什么是大小端2.2 为什么有大小端2.3…

Python 基于卷积神经网络手写数字识别

Ubuntu系统&#xff1a;22.04 python版本&#xff1a;3.9 安装依赖库&#xff1a; pip install tensorflow2.13 matplotlib numpy -i https://mirrors.aliyun.com/pypi/simple 代码实现&#xff1a; import tensorflow as tf from tensorflow.keras.models import Sequent…

ElectronBot复刻-电路测试篇

typec-16p 接口部分 USB1&#xff08;Type - C 接口&#xff09;&#xff1a;这是通用的 USB Type - C 接口&#xff0c;具备供电和数据传输功能。 GND 引脚&#xff08;如 A1、A12、B1、B12 等&#xff09;&#xff1a;接地引脚&#xff0c;用于提供电路的参考电位&#xff0…

ESP8266+STM32 AT驱动程序,心知天气API 记录时间: 2025年5月26日13:24:11

接线为 串口2 接入ESP8266 esp8266.c #include "stm32f10x.h"//8266预处理文件 #include "esp8266.h"//硬件驱动 #include "delay.h" #include "usart.h"//用得到的库 #include <string.h> #include <stdio.h> #include …

CDN安全加速:HTTPS加密最佳配置方案

CDN安全加速的HTTPS加密最佳配置方案需从证书管理、协议优化、安全策略到性能调优进行全链路设计&#xff0c;以下是核心实施步骤与注意事项&#xff1a; ​​一、证书配置与管理​​ ​​证书选择与格式​​ ​​证书类型​​&#xff1a;优先使用受信任CA机构颁发的DV/OV/EV证…

【前端】Twemoji(Twitter Emoji)

目录 注意使用Vue / React 项目 验证 Twemoji 的作用&#xff1a; Twemoji 会把你网页/应用中的 Emoji 字符&#xff08;如 &#x1f604;&#xff09;自动替换为 Twitter 风格的图片&#xff08;SVG/PNG&#xff09;&#xff1b; 它不依赖系统字体&#xff0c;因此在 Android、…

GCN图神经网络的光伏功率预测

一、GCN图神经网络的核心优势 图结构建模能力 GCN通过邻接矩阵&#xff08;表示节点间关系&#xff09;和节点特征矩阵&#xff08;如气象数据、历史功率&#xff09;进行特征传播&#xff0c;能够有效捕捉光伏电站间的空间相关性。其核心公式为&#xff1a; H ( l 1 ) σ (…

按照状态实现自定义排序的方法

方法一&#xff1a;使用 MyBatis-Plus 的 QueryWrapper 自定义排序 在查询时动态构建排序规则&#xff0c;通过 CASE WHEN 语句实现优先级排序&#xff1a; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.stereotype.Ser…

【计算机网络】IPv6和NAT网络地址转换

IPv6 IPv6协议使用由单/双冒号分隔一组数字和字母&#xff0c;例如2001:0db8:85a3:0000:0000:8a2e:0370:7334&#xff0c;分成8段。IPv6 使用 128 位互联网地址&#xff0c;有 2 128 2^{128} 2128个IP地址无状态地址自动配置&#xff0c;主机可以通过接口标识和网络前缀生成全…

【Redis】string

String 字符串 字符串类型是 Redis 最基础的数据类型&#xff0c;关于字符串需要特别注意&#xff1a; 首先 Redis 中所有的键的类型都是字符串类型&#xff0c;而且其他几种数据结构也都是在字符串的基础上构建的。字符串类型的值实际可以是字符串&#xff0c;包含一般格式的…

基于ELK的分布式日志实时分析与可视化系统设计

目录 一、ELK平台介绍 1.ELK概述 2.Elasticsearch 3.Logstash 4.Kibana 二、部署ES群集 1.资源清单 2.基本配置 3.安装Elasticsearch&#xff08;elk1上、elk2上、elk3上&#xff09; 4.安装logstash&#xff08;elk1上&#xff09; 5.Filebeat 6.安装Kibana&#x…

电机控制选 STM32 还是 DSP?技术选型背后的现实博弈

现在搞电机控制&#xff0c;圈里人都门儿清 —— 主流方案早就被 STM32 这些 Cortex-M 单片机给拿捏了。可要是撞上系统里的老甲方&#xff0c;技术认知还停留在诺基亚砸核桃的年代&#xff0c;非揪着 DSP 不放&#xff0c;咱也只能赔笑脸&#xff1a;“您老说的对&#xff0c;…

【案例分享】蓝牙红外线影音遥控键盘:瑞昱RTL8752CJF

蓝牙红外线影音遥控键盘 Remotec的无线控制键盘采用瑞昱蓝牙RTL8752CJF解决方案&#xff0c;透过蓝牙5.0与手机配对后&#xff0c;连线至 Remotec 红外 code server 取得对应影音视觉设备的红外 code后&#xff0c;即可控制多达2个以上的影音视觉设备&#xff0c;像是智能电视…

PostgreSQL如何更新和删除表数据

这节说下怎样更新和删除表数据&#xff0c;当然认识命令了&#xff0c;可以问AI帮忙写。 接上节先看下天气表weather的数据&#xff0c;增加了杭州和西安的数据&#xff1a; 一.UPDATE更新命令 用UPDATE命令更新现有的行。 假设所有 杭州 5月12日的温度低了两度&#xff0c;用…

简单三步FastAdmin 开源框架的安装

简单三步FastAdmin 开源框架的安装 第一步&#xff1a;新建站点1&#xff0c;在宝塔面板中&#xff0c;创建一个新的站点&#xff0c;并填写项目域名。 第二步&#xff1a;上传框架1&#xff0c;框架下载2&#xff0c;上传解压缩 第三步&#xff1a;配置并安装1&#xff0c;进入…

使用 pytesseract 构建一个简单 OCR demo

简介 pytesseract 库是 Google Tesseract OCR &#xff08;光学字符识别&#xff09;引擎的一个 Python 封装库&#xff0c;使用广泛且功能强大。 构建 使用 pytesseract 构建一个简单 OCR demo。 步骤一&#xff1a;安装必要的库 您需要在您的 Python 环境中安装 pytessera…

十三: 神经网络的学习

这里所说的“学习”是指从训练数据中自动获取最优权重参数的过程。为了使神经网络能进行学习&#xff0c;将导入损失函数这一指标。而学习的目的就是以该损失函数为基准&#xff0c;找出能使它的值达到最小的权重参数。为了找出尽可能小的损失函数的值&#xff0c;我们将介绍利…

AWS 创建VPC 并且添加权限控制

AWS 创建VPC 并且添加权限控制 以下是完整的从0到1在AWS中创建VPC并配置权限的步骤&#xff08;包含网络配置、安全组权限和实例访问&#xff09;&#xff1a; 1. 创建VPC 步骤&#xff1a; 登录AWS控制台 访问 AWS VPC控制台&#xff0c;点击 创建VPC。 配置基础信息 名称…

ICASSP2025丨融合语音停顿信息与语言模型的阿尔兹海默病检测

阿尔兹海默病&#xff08;Alzheimers Disease, AD&#xff09;是一种以认知能力下降和记忆丧失为特征的渐进性神经退行性疾病&#xff0c;及早发现对于其干预和治疗至关重要。近期&#xff0c;清华大学语音与音频技术实验室&#xff08;SATLab&#xff09;提出了一种将停顿信息…