C 语言函数指针实战:回调、函数表与 void 指针进阶用法
函数指针赋予 C 语言强大能力,允许函数通过内存地址直接操作数据而非复制值。通过向指针参数传递地址,函数可修改原变量,实现原地交换、动态回调、高阶函数等模式。
- 函数指针示例
- 数组参数函数
- 返回数组的函数
- 函数指针
- 函数指针数组
- 使用 void 指针的函数
- 作为参数的函数指针
函数指针示例
经典 swap 例程演示函数如何通过地址交换两变量值。
void swap (int *a, int *b);
int main() {
int m = 25;
int n = 100;
printf("m is %d, n is %d\n", m, n);
swap(&m, &n);
printf("m is %d, n is %d\n", m, n);
return 0;
}
void swap (int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
输出:
m is 25, n is 100 m is 100, n is 25

- 声明
swap接受两个整型指针 main初始化 m、n 并打印- 调用
swap(&m, &n)传递地址 swap内用临时变量交换值- 解引用指针读写实际数据
数组参数函数
数组传参时退化为指针。下例通过指针遍历求和:
int add_array (int *a, int num_elements);
int main() {
int Tab[5] = {100, 220, 37, 16, 98};
printf("Total summation is %d\n", add_array(Tab, 5));
return 0;
}
int add_array (int *p, int size) {
int total = 0;
for (int k = 0; k < size; k++) {
total += p[k]; /* 等价于 total += *p; p++; */
}
return total;
}
输出:
Total summation is 471

- 定义
add_array接受指针与大小,返回求和 - 传入数组名
Tab(退化为指针)及长度
返回数组的函数
函数可返回静态数组指针,适合调用者需要临时数组且不想管理内存的场景。
#include <stdio.h>
int * build_array();
int main() {
int *a;
a = build_array(); /* 获取前 5 个整数 */
for (int k = 0; k < 5; k++) printf("%d\n", a[k]);
return 0;
}
int * build_array() {
static int Tab[5] = {1,2,3,4,5};
return Tab;
}
输出:
1 2 3 4 5

- 声明返回静态数组指针的函数
- 用返回指针遍历打印数组内容
函数指针
函数指针持有函数入口地址,支持动态分发与回调。声明语法需在星号外加括号以免歧义。
return_type (*function_name)(arguments)
示例:通过指针调用例程。
#include <stdio.h>
void Hi_function (int times); /* 函数 */
int main() {
void (*function_ptr)(int); /* 函数指针 */
function_ptr = Hi_function; /* 赋值 */
function_ptr(3); /* 调用 */
return 0;
}
void Hi_function (int times) {
for (int k = 0; k < times; k++) printf("Hi\n");
}
输出:
Hi Hi Hi

- 定义普通函数
- 声明匹配签名的函数指针
- 将指针指向函数名
- 通过指针调用函数
函数指针数组
将多个函数指针存入数组可实现表驱动逻辑,类似 switch 语句。下例演示简易计算器:
#include <stdio.h>
int sum(int num1, int num2);
int sub(int num1, int num2);
int mult(int num1, int num2);
int divi(int num1, int num2);
int main() {
int x, y, choice, result;
int (*ope[4])(int, int);
ope[0] = sum;
ope[1] = sub;
ope[2] = mult;
ope[3] = divi;
printf("Enter two integer numbers: ");
scanf("%d%d", &x, &y);
printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: ");
scanf("%d", &choice);
result = ope[choice](x, y);
printf("%d", result);
return 0;
}
int sum(int x, int y) {return x + y;}
int sub(int x, int y) {return x - y;}
int mult(int x, int y) {return x * y;}
int divi(int x, int y) {return y != 0 ? x / y : 0;}
结果: 输入 13 48 2 → 624

- 定义四个算术函数
- 创建四元素函数指针数组,签名一致
- 各指针指向对应函数
- 获取用户选择并调用选定函数
使用 void 指针的函数
Void 指针提供类型无关的数据访问。用作函数参数时,允许例程接受任意类型,前提是调用者提供正确强转。
void * cube (const void *);
示例程序:
#include <stdio.h>
void* cube (const void* num);
int main() {
int x = 4;
int cube_int = (int)cube(&x);
printf("%d cubed is %d\n", x, cube_int);
return 0;
}
void* cube (const void *num) {
int result = (*(int *)num) * (*(int *)num) * (*(int *)num);
return (void*)result;
}
结果: 4 cubed is 64

- 定义接受 const void 指针、返回 void 指针的函数
- 强转为
int *访问值 - 计算立方并强转回
void *返回
作为参数的函数指针
将函数指针传给另一函数是常见回调模式。标准库 qsort 即利用此技术排序任意类型数组。
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *));
排序整型数组示例:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *, const void *);
int main() {
int arr[5] = {52, 14, 50, 48, 13};
size_t num = sizeof(arr)/sizeof(arr[0]);
size_t width = sizeof(arr[0]);
qsort((void *)arr, num, width, compare);
for (size_t i = 0; i < num; i++) printf("%d ", arr[i]);
return 0;
}
int compare (const void *elem1, const void *elem2) {
int a = *(int *)elem1;
int b = *(int *)elem2;
return (a - b);
}
结果: 13 14 48 50 52

- 实现
compare返回负/零/正表示两整数大小关系 - 用
sizeof计算数组元素数与元素宽度 - 调用
qsort传入数组、个数、宽度、比较函数 - 打印排序后数组验证
C语言
- C 语言用户自定义函数四大模式对比:参数与返回值的设计权衡
- C++ do-while 循环详解:语法、实战示例与嵌套循环
- C++ 指针精通:核心概念、代码示例与实战应用
- C++ 运算符重载实战指南:语法、方法、限制与代码示例
- C++ 函数详解:从声明到调用的实战指南
- C# 集合实战教程:ArrayList、Stack、Queue、Hashtable 等核心类型全解析
- C 语言指针完全指南:类型、用法与最佳实践
- Python str.count() 完全指南:统计字符与子串出现次数实战
- 精通 Python Lambda 函数:实用示例与最佳实践
- Python round() 函数详解与实战示例
- 精通 Python map() 函数:语法、示例与最佳实践
- Python timeit():精准测量代码执行时间与实战示例