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

目录

[1.1 函数指针的概念和应用](#1.1 函数指针的概念和应用)

[1.2 赋值与内存模型](#1.2 赋值与内存模型)

[1.3 调用方式与注意事项](#1.3 调用方式与注意事项)

二、函数指针的使用

[2.1 函数指针的定义和访问](#2.1 函数指针的定义和访问)

[2.2 动态调度:用户输入驱动函数执行](#2.2 动态调度:用户输入驱动函数执行)

[2.3 函数指针数组进阶应用](#2.3 函数指针数组进阶应用)

[2.4 函数作为参数的高阶抽象](#2.4 函数作为参数的高阶抽象)

三、回调函数

[3.1 指针函数vs函数指针](#3.1 指针函数vs函数指针)

[3.2 指针函数应用](#3.2 指针函数应用)

[3.3 回调函数机制解析](#3.3 回调函数机制解析)

[3.4 消息循环](#3.4 消息循环)


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

1.1 函数指针的概念和应用

·核心概念

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

例如:

input (*ptr)(int, char)

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

·应用

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

1.2 赋值与内存模型

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

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

1.3 调用方式与注意事项

cpp 复制代码
int result1 = ptr(3,5);
int result2 = (*ptr)(3,5);

⚠️注意事项

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

二、函数指针的使用

2.1 函数指针的定义和访问

cpp 复制代码
//使用typedef简化声明
typedef int (*Func)(int, int);

Func ad = add; //定义简洁
int res = ad(10,20);

·类型别名优势:

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

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

·头文件

cpp 复制代码
#include <stdio.h>

·定义add和sub

cpp 复制代码
int add(int a,int b) { return a+b; }
int sub(int a,int b) { return a-b; }

·主函数

cpp 复制代码
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 函数指针数组进阶应用

cpp 复制代码
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 函数作为参数的高阶抽象

cpp 复制代码
// 通用排序函数(接收比较函数作为参数)
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 指针函数应用

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

3.3 回调函数机制解析

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

  1. 调用方定义函数原型并预留指针函数
  2. 被调用方(如库函数)在特定事件发生时调用该指针
cpp 复制代码
// 模拟操作系统定时器回调
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 消息循环

cpp 复制代码
// 简化的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语言学习合集(草稿版)👾

相关推荐
纨妙2 分钟前
python打卡day59
开发语言·python
wuxuanok8 分钟前
Web后端开发-请求响应
java·开发语言·笔记·学习
i7i8i9com21 分钟前
后端微服务基础架构Spring Cloud
学习
Sally璐璐28 分钟前
IPSAN 共享存储详解:架构、优化与落地实践指南
开发语言·php
像风一样的男人@38 分钟前
python --货车装厢问题
开发语言·python
Humbunklung1 小时前
Rust枚举:让数据类型告别单调乏味
开发语言·后端·rust
蜡笔小电芯1 小时前
【C语言】指针与回调机制学习笔记
c语言·笔记·学习
Y1nhl1 小时前
力扣_链表_python版本
开发语言·python·算法·leetcode·链表·职场和发展
OEC小胖胖1 小时前
深入理解 Vue.js 响应式原理及其在 Web 前端开发中的应用
开发语言·前端·javascript·vue.js·web
qq_401700411 小时前
C语言中位运算以及获取低8位和高8位、高低位合并
c语言·开发语言·算法