C语言函数指针解析
一、函数指针的本质
函数指针是存储函数内存地址的变量,它允许程序在运行时动态调用不同的函数。与数据指针不同,函数指针指向的是可执行代码段。
c
/* 典型声明方式 */
int (*func_ptr)(int, int); // 可指向任何接受两个int参数且返回int的函数
二、核心语法详解
1. 声明与初始化
函数指针的声明必须与目标函数签名严格匹配:
c
#include <stdio.h>
// 基础函数定义
int Add(int a, int b) { return a + b; }
int Sub(int a, int b) { return a - b; }
int main() {
// 初始化方式(两种等效)
int (*fp1)(int, int) = Add; // 直接赋值
int (*fp2)(int, int) = ⋐ // 取地址赋值
printf("5+3=%d\n", fp1(5, 3)); // 输出8
printf("5-3=%d\n", (*fp2)(5, 3)); // 输出2
return 0;
}
2. 类型定义简化
使用typedef
提升代码可读性:
c
typedef int (*ArithmeticFunc)(int, int);
ArithmeticFunc fp = Add; // 简化后的声明
三、实际应用场景
1. 回调函数实现
函数指针最常见的用途是实现回调机制:
c
// 回调函数类型定义
typedef void (*Logger)(const char*);
// 业务函数
void ProcessData(int data, Logger log) {
char buf[50];
sprintf(buf, "Processing: %d", data);
log(buf); // 通过函数指针回调
}
// 具体回调实现
void ConsoleLogger(const char* msg) {
printf("[LOG] %s\n", msg);
}
int main() {
ProcessData(42, ConsoleLogger); // 输出:[LOG] Processing: 42
return 0;
}
2. 函数指针数组
创建可扩展的操作表:
c
ArithmeticFunc operations[] = {
Add,
Sub,
[](int a, int b) { return a * b; }, // 注意:此lambda语法为C++特性,纯C需替换为具名函数
[](int a, int b) { return a / b; }
};
// 纯C替代方案
int Multiply(int a, int b) { return a * b; }
int Divide(int a, int b) { return a / b; }
ArithmeticFunc c_operations[] = {Add, Sub, Multiply, Divide};
四、工程实践建议
1. 错误预防
c
/* 必须检查空指针 */
if (func_ptr != NULL) {
func_ptr(1, 2);
}
/* 避免签名不匹配 */
// int WrongFunc(float a, float b);
// func_ptr = WrongFunc; // 编译错误!
2. 典型应用案例
c
/* 标准库qsort用法 */
#include <stdlib.h>
int CompareInt(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}
int main() {
int arr[] = {5, 2, 9, 1};
qsort(arr, 4, sizeof(int), CompareInt);
// 排序结果:1, 2, 5, 9
return 0;
}
五、总结对比
特性 | 函数指针 | 普通函数调用 |
---|---|---|
运行时灵活性 | 可在运行时改变指向 | 编译期固定 |
性能开销 | 无额外开销 | 无额外开销 |
典型用途 | 回调/插件/策略模式 | 直接功能实现 |
提示:在C++中可考虑更安全的
std::function
,但在C项目中函数指针仍是核心机制。