C语言函数指针与回调函数实战指南

函数指针是C语言中最强大的特性之一,它使得程序设计更加灵活,支持回调机制、插件系统和多态编程。

1. 函数指针基础

函数指针的声明和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>

// 普通函数
int add(int a, int b) {
return a + b;
}

int subtract(int a, int b) {
return a - b;
}

int multiply(int a, int b) {
return a * b;
}

void basicFunctionPointers() {
printf("=== 函数指针基础 ===\n");

// 声明函数指针
int (*operation)(int, int);

// 指向不同的函数
operation = add;
printf("10 + 5 = %d\n", operation(10, 5));

operation = subtract;
printf("10 - 5 = %d\n", operation(10, 5));

operation = multiply;
printf("10 * 5 = %d\n", operation(10, 5));

// 直接调用函数指针
printf("直接调用:10 + 3 = %d\n", add(10, 3));
printf("通过指针调用:10 + 3 = %d\n", (*operation)(10, 3));
}

函数指针数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

// 计算器函数
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) {
if (b != 0) return a / b;
printf("错误:除零\n");
return 0;
}

void functionPointerArray() {
printf("\n=== 函数指针数组 ===\n");

// 函数指针数组
int (*operations[])(int, int) = {add, subtract, multiply, divide};
char *op_names[] = {"+", "-", "*", "/"};

int a = 20, b = 4;
int num_ops = sizeof(operations) / sizeof(operations[0]);

printf("使用函数指针数组实现计算器:\n");
for (int i = 0; i < num_ops; i++) {
int result = operations[i](a, b);
printf("%d %s %d = %d\n", a, op_names[i], b, result);
}
}

2. 回调函数机制

基本回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>

// 回调函数类型定义
typedef void (*CallbackFunction)(int result);

// 不同的回调函数
void printResult(int result) {
printf("计算结果:%d\n", result);
}

void printSquare(int result) {
printf("结果的平方:%d\n", result * result);
}

void printDouble(int result) {
printf("结果的两倍:%d\n", result * 2);
}

// 使用回调函数的计算函数
void calculate(int a, int b, int (*operation)(int, int), CallbackFunction callback) {
int result = operation(a, b);
callback(result); // 调用回调函数
}

void callbackExample() {
printf("\n=== 回调函数示例 ===\n");

printf("加法运算:\n");
calculate(10, 5, add, printResult);
calculate(10, 5, add, printSquare);
calculate(10, 5, add, printDouble);

printf("\n乘法运算:\n");
calculate(6, 7, multiply, printResult);
calculate(6, 7, multiply, printSquare);
}

事件处理系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LISTENERS 10

// 事件类型
typedef enum {
EVENT_BUTTON_CLICK,
EVENT_KEY_PRESS,
EVENT_MOUSE_MOVE
} EventType;

// 事件数据结构
typedef struct {
EventType type;
int x, y; // 坐标
char key; // 按键
} Event;

// 事件监听器函数类型
typedef void (*EventListener)(const Event *event);

// 事件系统结构
typedef struct {
EventListener listeners[MAX_LISTENERS];
int listener_count;
} EventSystem;

// 全局事件系统
static EventSystem g_event_system = {0};

// 注册事件监听器
void addEventListener(EventListener listener) {
if (g_event_system.listener_count < MAX_LISTENERS) {
g_event_system.listeners[g_event_system.listener_count++] = listener;
printf("事件监听器已注册\n");
} else {
printf("错误:监听器数量已达上限\n");
}
}

// 触发事件
void fireEvent(const Event *event) {
printf("触发事件...\n");
for (int i = 0; i < g_event_system.listener_count; i++) {
g_event_system.listeners[i](event);
}
}

// 具体的事件处理函数
void onButtonClick(const Event *event) {
if (event->type == EVENT_BUTTON_CLICK) {
printf(" [按钮监听器] 按钮在位置 (%d, %d) 被点击\n", event->x, event->y);
}
}

void onKeyPress(const Event *event) {
if (event->type == EVENT_KEY_PRESS) {
printf(" [键盘监听器] 按键 '%c' 被按下\n", event->key);
}
}

void onMouseMove(const Event *event) {
if (event->type == EVENT_MOUSE_MOVE) {
printf(" [鼠标监听器] 鼠标移动到 (%d, %d)\n", event->x, event->y);
}
}

// 通用事件记录器
void eventLogger(const Event *event) {
const char *event_names[] = {"BUTTON_CLICK", "KEY_PRESS", "MOUSE_MOVE"};
printf(" [日志] 事件类型:%s\n", event_names[event->type]);
}

void eventSystemExample() {
printf("\n=== 事件处理系统 ===\n");

// 注册事件监听器
addEventListener(onButtonClick);
addEventListener(onKeyPress);
addEventListener(onMouseMove);
addEventListener(eventLogger);

// 创建和触发不同类型的事件
Event button_event = {EVENT_BUTTON_CLICK, 100, 200, 0};
Event key_event = {EVENT_KEY_PRESS, 0, 0, 'A'};
Event mouse_event = {EVENT_MOUSE_MOVE, 150, 250, 0};

printf("\n模拟按钮点击事件:\n");
fireEvent(&button_event);

printf("\n模拟按键事件:\n");
fireEvent(&key_event);

printf("\n模拟鼠标移动事件:\n");
fireEvent(&mouse_event);
}

3. 高级函数指针应用

策略模式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdio.h>
#include <stdlib.h>

// 排序策略函数类型
typedef void (*SortStrategy)(int arr[], int n);

// 冒泡排序
void bubbleSort(int arr[], int n) {
printf("使用冒泡排序\n");
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

// 选择排序
void selectionSort(int arr[], int n) {
printf("使用选择排序\n");
for (int i = 0; i < n - 1; i++) {
int min_idx = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}
if (min_idx != i) {
int temp = arr[i];
arr[i] = arr[min_idx];
arr[min_idx] = temp;
}
}
}

// 插入排序
void insertionSort(int arr[], int n) {
printf("使用插入排序\n");
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}

// 排序上下文
typedef struct {
SortStrategy strategy;
} SortContext;

// 设置排序策略
void setSortStrategy(SortContext *context, SortStrategy strategy) {
context->strategy = strategy;
}

// 执行排序
void executeSort(SortContext *context, int arr[], int n) {
if (context->strategy != NULL) {
context->strategy(arr, n);
} else {
printf("错误:未设置排序策略\n");
}
}

// 打印数组
void printArray(int arr[], int n, const char *title) {
printf("%s: ", title);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

void strategyPatternExample() {
printf("\n=== 策略模式示例 ===\n");

int original[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(original) / sizeof(original[0]);

SortContext context;

// 测试不同的排序策略
SortStrategy strategies[] = {bubbleSort, selectionSort, insertionSort};
const char *strategy_names[] = {"冒泡排序", "选择排序", "插入排序"};
int num_strategies = sizeof(strategies) / sizeof(strategies[0]);

for (int i = 0; i < num_strategies; i++) {
// 复制原始数组
int arr[7];
for (int j = 0; j < n; j++) {
arr[j] = original[j];
}

printf("\n--- %s ---\n", strategy_names[i]);
printArray(arr, n, "排序前");

setSortStrategy(&context, strategies[i]);
executeSort(&context, arr, n);

printArray(arr, n, "排序后");
}
}

函数指针作为结构体成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 动物接口(使用函数指针模拟)
typedef struct Animal {
char name[50];
void (*speak)(struct Animal *self);
void (*move)(struct Animal *self);
void (*eat)(struct Animal *self, const char *food);
} Animal;

// 狗的行为实现
void dogSpeak(Animal *self) {
printf("%s 说:汪汪!\n", self->name);
}

void dogMove(Animal *self) {
printf("%s 在跑步\n", self->name);
}

void dogEat(Animal *self, const char *food) {
printf("%s 正在吃 %s\n", self->name, food);
}

// 猫的行为实现
void catSpeak(Animal *self) {
printf("%s 说:喵喵!\n", self->name);
}

void catMove(Animal *self) {
printf("%s 在优雅地走路\n", self->name);
}

void catEat(Animal *self, const char *food) {
printf("%s 正在优雅地享用 %s\n", self->name, food);
}

// 鸟的行为实现
void birdSpeak(Animal *self) {
printf("%s 说:啾啾!\n", self->name);
}

void birdMove(Animal *self) {
printf("%s 在天空中飞翔\n", self->name);
}

void birdEat(Animal *self, const char *food) {
printf("%s 正在啄食 %s\n", self->name, food);
}

// 创建动物的工厂函数
Animal* createDog(const char *name) {
Animal *dog = (Animal*)malloc(sizeof(Animal));
if (dog != NULL) {
strcpy(dog->name, name);
dog->speak = dogSpeak;
dog->move = dogMove;
dog->eat = dogEat;
}
return dog;
}

Animal* createCat(const char *name) {
Animal *cat = (Animal*)malloc(sizeof(Animal));
if (cat != NULL) {
strcpy(cat->name, name);
cat->speak = catSpeak;
cat->move = catMove;
cat->eat = catEat;
}
return cat;
}

Animal* createBird(const char *name) {
Animal *bird = (Animal*)malloc(sizeof(Animal));
if (bird != NULL) {
strcpy(bird->name, name);
bird->speak = birdSpeak;
bird->move = birdMove;
bird->eat = birdEat;
}
return bird;
}

// 动物行为测试
void testAnimal(Animal *animal, const char *food) {
if (animal != NULL) {
animal->speak(animal);
animal->move(animal);
animal->eat(animal, food);
printf("\n");
}
}

void polymorphismExample() {
printf("\n=== 多态性示例 ===\n");

// 创建不同类型的动物
Animal *animals[] = {
createDog("旺财"),
createCat("咪咪"),
createBird("小黄")
};

const char *foods[] = {"骨头", "鱼", "虫子"};
int num_animals = sizeof(animals) / sizeof(animals[0]);

// 多态调用
for (int i = 0; i < num_animals; i++) {
testAnimal(animals[i], foods[i]);
}

// 清理内存
for (int i = 0; i < num_animals; i++) {
free(animals[i]);
}
}

4. 函数指针与泛型编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 比较函数类型
typedef int (*CompareFunction)(const void *a, const void *b);

// 整数比较函数
int compareInts(const void *a, const void *b) {
int ia = *(const int*)a;
int ib = *(const int*)b;
return (ia > ib) - (ia < ib);
}

// 字符串比较函数
int compareStrings(const void *a, const void *b) {
return strcmp(*(const char**)a, *(const char**)b);
}

// 浮点数比较函数
int compareFloats(const void *a, const void *b) {
float fa = *(const float*)a;
float fb = *(const float*)b;
return (fa > fb) - (fa < fb);
}

// 通用排序函数(简化版快速排序)
void genericSort(void *base, size_t num, size_t size, CompareFunction compare) {
// 这里使用标准库的qsort作为示例
qsort(base, num, size, compare);
}

// 通用打印函数类型
typedef void (*PrintFunction)(const void *item);

// 打印整数
void printInt(const void *item) {
printf("%d ", *(const int*)item);
}

// 打印字符串
void printString(const void *item) {
printf("%s ", *(const char**)item);
}

// 打印浮点数
void printFloat(const void *item) {
printf("%.2f ", *(const float*)item);
}

// 通用数组打印函数
void printArray(const void *base, size_t num, size_t size, PrintFunction print) {
const char *ptr = (const char*)base;
for (size_t i = 0; i < num; i++) {
print(ptr + i * size);
}
printf("\n");
}

void genericProgrammingExample() {
printf("\n=== 泛型编程示例 ===\n");

// 整数数组排序
printf("整数数组排序:\n");
int ints[] = {64, 34, 25, 12, 22, 11, 90};
int int_count = sizeof(ints) / sizeof(ints[0]);

printf("排序前:");
printArray(ints, int_count, sizeof(int), printInt);

genericSort(ints, int_count, sizeof(int), compareInts);

printf("排序后:");
printArray(ints, int_count, sizeof(int), printInt);

// 字符串数组排序
printf("\n字符串数组排序:\n");
const char *strings[] = {"banana", "apple", "cherry", "date"};
int str_count = sizeof(strings) / sizeof(strings[0]);

printf("排序前:");
printArray(strings, str_count, sizeof(char*), printString);

genericSort(strings, str_count, sizeof(char*), compareStrings);

printf("排序后:");
printArray(strings, str_count, sizeof(char*), printString);

// 浮点数数组排序
printf("\n浮点数数组排序:\n");
float floats[] = {3.14f, 2.71f, 1.41f, 1.73f};
int float_count = sizeof(floats) / sizeof(floats[0]);

printf("排序前:");
printArray(floats, float_count, sizeof(float), printFloat);

genericSort(floats, float_count, sizeof(float), compareFloats);

printf("排序后:");
printArray(floats, float_count, sizeof(float), printFloat);
}

5. 主函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
printf("C语言函数指针与回调函数示例\n");
printf("================================\n");

basicFunctionPointers();
functionPointerArray();
callbackExample();
eventSystemExample();
strategyPatternExample();
polymorphismExample();
genericProgrammingExample();

return 0;
}

总结

函数指针的核心应用场景:

  1. 回调机制:实现事件驱动编程
  2. 策略模式:运行时选择算法
  3. 多态性:模拟面向对象编程
  4. 泛型编程:编写通用的数据处理函数
  5. 插件系统:动态加载和调用功能模块
  6. 状态机:根据状态调用不同的处理函数

掌握函数指针能让你的C代码更加灵活和可扩展,是进阶C编程的重要技能。

版权所有,如有侵权请联系我