C 语言 - 回调函数

回调函数

回调函数是作为参数传递给另一个函数的函数。

接收函数可以在需要时回调(运行)它

这是使代码灵活且可重用的强大方式——您可以在不改变主要逻辑的情况下决定应该运行哪个函数。

在 C 语言中,回调函数通常使用函数指针来实现。

简单回调示例

这是一个基本示例,展示了函数如何"回调"另一个函数:

实例

将一个函数作为参数传递给另一个函数:

void sayHello() {
  printf("Hello from the callback!\n");
}

void runCallback(void (*callback)()) {
  printf("Before calling the callback...\n");
  callback();
  printf("After calling the callback.\n");
}

int main() {
  runCallback(sayHello);
  return 0;
}

亲自试一试

在这个示例中:

  • sayHello() 是一个打印消息的普通函数。
  • runCallback() 接收一个函数指针作为参数。
  • runCallback(sayHello) 运行时,它在内部调用 sayHello()

注意:"回调"一词源于一个函数"回调"了之前传递给它的另一个函数这一事实。

带参数的回调

您也可以传递带参数的函数 - 只需确保函数指针类型匹配:

实例

将带参数的函数作为回调传递:

void addNumbers(int a, int b) {
  printf("The sum is: %d\n", a + b);
}

void calculate(void (*callback)(int, int), int x, int y) {
  callback(x, y);
}

int main() {
  calculate(addNumbers, 5, 3);
  return 0;
}

亲自试一试

在这里,calculate() 接收一个函数和两个数字,然后使用这些数字作为参数调用该函数(本例中是 addNumbers())。

多个回调

您可以使用回调,让一个函数根据您传入的函数不同而表现不同。这在排序、过滤和事件处理代码中很常见。

实例

使用不同的回调函数执行不同的操作:

void greetMorning() { printf("Good morning!\n"); }
void greetEvening() { printf("Good evening!\n"); }

void greet(void (*callback)()) {
  callback();
}

int main() {
  greet(greetMorning);
  greet(greetEvening);
  return 0;
}

亲自试一试

根据传递的函数不同,程序产生不同的输出 - 而无需更改 greet() 本身。

实际应用示例:在 qsort() 中使用回调

许多 C 标准库函数都使用回调。例如,<stdlib.h> 中的 qsort() 函数在排序时使用回调来比较元素。

您提供比较函数,qsort() 在需要时调用它。这将排序元素:

实例

#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) {
  return (*(int*)a - *(int*)b);
}

int main() {
  int numbers[] = { 5, 2, 9, 1, 7 };
  int size = sizeof(numbers) / sizeof(numbers[0]);

  qsort(numbers, size, sizeof(int), compare);

  for (int i = 0; i < size; i++) {
    printf("%d ", numbers[i]);
  }
  return 0;
}

亲自试一试

在这里,compare()qsort() 用于决定如何对数字排序的回调函数。

总结

  • 回调函数是作为参数传递给另一个函数的函数。
  • 它允许一个函数调用另一个函数,而无需预先知道其名称。
  • 回调使代码更灵活、更可重用。
  • 它们在 C 标准库(如 qsort())中使用。