C 语言 - 函数指针

函数指针

函数指针类似于普通指针,但它不是指向变量,而是指向函数

这意味着它存储了一个函数的地址,允许您使用该指针来调用那个函数。

函数指针让您可以在程序运行时决定运行哪个函数,或者当您想将一个函数作为参数传递给另一个函数时使用。

可以把它想象成保存一个电话号码 - 指针知道函数在内存中的位置,这样您以后就可以 "呼叫" 它。

声明函数指针

声明函数指针的一般语法是:

returnType (*pointerName)(parameterType1, parameterType2, ...);

例如:

int (*ptr)(int, int);

这意味着 ptr 是一个指向函数的指针,该函数接受两个 int 值并返回一个 int

将函数赋值给指针

您可以通过两种方式将函数赋值给指针:

ptr = add;
ptr = &add;

两种方式相同,因为函数名本身已经代表了它在内存中的地址。

通过指针调用函数

一旦指针被赋值,您可以通过两种方式调用函数:

ptr(5, 3);
(*ptr)(5, 3);

两种方式都有效,并且做的事情相同。

函数指针示例

既然您知道了如何声明和赋值函数指针,让我们看一个完整的例子:

实例

一个指向将两个数相加的函数的指针:

int add(int a, int b) {
  return a + b;
}

int main() {
  int (*ptr)(int, int) = add;
  int result = ptr(5, 3);
  printf("Result: %d", result);
  return 0;
}

亲自试一试

在这里:

  • ptr 是一个指向函数 add() 的指针。
  • ptr(5, 3) 使用指针调用函数。

这与直接调用 add(5, 3) 的效果完全相同。

注意:函数名本身指向其代码在内存中的起始位置。这意味着函数名本身已经起到了指针的作用!声明函数指针只是为您提供了一个可以保存该地址的变量——因此您可以更改它或传递它。

将函数作为参数传递

函数指针可以传递给其他函数 - 这被称为回调

它允许一个函数调用您作为输入提供的另一个函数。

实例

将函数指针传递给另一个函数:

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

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

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

亲自试一试

在这里,greet() 将另一个函数作为参数并调用它。这常用于事件驱动的程序或需要用户提供回调函数的库中。

函数指针数组

您还可以将多个函数指针存储在一个数组中,这样您就可以在程序运行时选择要运行的函数。

此例使用函数指针数组运行三个不同的函数:

实例

void add() { printf("Add\n"); }
void subtract() { printf("Subtract\n"); }
void multiply() { printf("Multiply\n"); }

int main() {
  void (*operations[3])() = { add, subtract, multiply };
  for (int i = 0; i < 3; i++) {
    operations[i]();
  }
  return 0;
}

亲自试一试

这常用于简单的菜单、命令列表或计算器 - 任何您想根据用户输入调用不同函数的地方。

实例

一个使用函数指针数组的简单计算器:

void add(int a, int b) { printf("Result: %d\n", a + b); }
void subtract(int a, int b) { printf("Result: %d\n", a - b); }
void multiply(int a, int b) { printf("Result: %d\n", a * b); }

int main() {
  int choice, x = 10, y = 5;

  void (*operations[3])(int, int) = { add, subtract, multiply };

  printf("x = %d, y = %d\n\n", x, y);
  printf("Choose an operation:\n");
  printf("0: Add\n1: Subtract\n2: Multiply\n");
  scanf("%d", &choice);

  if (choice >= 0 && choice < 3) {
    operations[choice](x, y);
  } else {
    printf("Invalid choice!\n");
  }

  return 0;
}

亲自试一试

在这个程序中:

  • 三个数学函数(add()subtract()multiply())存储在一个数组中。
  • 用户通过输入数字选择运行哪一个。
  • 然后使用指针数组调用正确的函数。

这是一个简单的例子,展示了函数指针数组如何使程序更灵活和可重用。

函数指针 vs 普通函数

普通函数 函数指针
通过其名称直接调用 通过指针调用
函数在程序运行前决定 可以在程序运行时选择要调用的函数
适合简单代码 适合灵活且可重用的代码

总结

  • 函数指针存储函数的地址。
  • 您可以通过它声明、赋值和调用函数。
  • 它允许将函数作为参数传递给其他函数。
  • 对于回调、菜单和灵活的程序设计很有用。