【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语言学习合集(草稿版)👾

相关推荐
不写八个18 分钟前
Express教程【003】:Express获取查询参数
开发语言·express
虾球xz1 小时前
CppCon 2014 学习:Making C++ Code Beautiful
c++·学习
两点王爷4 小时前
Java spingboot项目 在docker运行,需要含GDAL的JDK
java·开发语言·docker
清晨朝暮6 小时前
【Linux 学习计划】-- 命令行参数 | 环境变量
linux·运维·学习
云泽8087 小时前
模块化设计,static和extern(面试题常见)
c语言·面试·职场和发展
万能螺丝刀17 小时前
java helloWord java程序运行机制 用idea创建一个java项目 标识符 关键字 数据类型 字节
java·开发语言·intellij-idea
朱剑君7 小时前
编程之巅:语言的较量
开发语言
Humbunklung7 小时前
Rust 编程实现猜数字游戏
开发语言·后端·rust
vvilkim7 小时前
深入理解C#数据类型:从基础到高级应用
开发语言·c#
2301_803652747 小时前
tiktoken学习
学习