C 语言中的函数指针

Jinku Hu 2023年10月12日
  1. 在 C 语言中使用 void (*func)() 符号来定义函数指针
  2. 使用函数指针数组实现类型通用编程特性
C 语言中的函数指针

本文将介绍如何在 C 语言中使用函数指针。

在 C 语言中使用 void (*func)() 符号来定义函数指针

函数指针是 C 语言程序设计中的又一个结构,它实现了动态函数调用、结中包含自己的方法等高级功能,类似于面向对象设计、类型通用程序设计等。需要注意的是,函数指针的声明可能有复杂的语法,即 void(*func)(void) 记号声明了指向 void 函数的指针,该函数不需要参数。虽然在下面的例子中,我们将取单一 int 参数的 printInt 函数的地址分配给 void(*func)(void) 型函数指针。一旦定义了名为 func 的函数指针,就可以用通常的函数调用符号 func(arg) 或用 dereferencing 运算符 (*func)(arg) 来调用它。

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

void printInt(int x) { printf("printed from printInt: %d\n", x); }

int main() {
  int input1 = 10233;

  void (*func)(int) = printInt;

  func(input1);
  (*func)(input1);

  exit(EXIT_SUCCESS);
}

输出:

printed from printInt: 10233
printed from printDouble: 11.234000

另外,我们也可以使用 typedef 为函数指针定义一个新的类型别名,使代码更易读。注意,不同的函数类型需要单独的 typedef 语句。在下面的代码示例中,我们定义了一个没有任何参数的 void 函数指针,尽管如此,printIntprintDouble 函数地址都存储在类型为 FuncPtr 的变量中。需要注意的是,特定函数的地址可以通过显式的&运算符或函数名本身的隐式赋值来获取,这在下一个例子中有所体现。

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

typedef void (*FuncPtr)();

void printInt(int x) { printf("printed from printInt: %d\n", x); }

void printDouble(double x) { printf("printed from printDouble: %f\n", x); }

int main() {
  int input1 = 10233;
  double input2 = 11.234;

  FuncPtr func1 = printInt;
  FuncPtr func2 = printDouble;

  func1(input1);
  func2(input2);

  exit(EXIT_SUCCESS);
}

输出:

printed from printInt: 10233
printed from printDouble: 11.234000

使用函数指针数组实现类型通用编程特性

像其他对象一样,可以用括号 [] 符号定义一个函数指针数组。在运行时可以利用这个数组方便地选择和调用特定的函数。请注意,我们使用的是关键字 _Generic,它是 switch 一样的表达式,让用户根据控制表达式的类型评价来选择具体的情况。因此,我们实现了下面的代码示例,根据 switch 条件中传递的变量类型,调用相应的 print 函数。请注意,enum 类型也被用来定义不同情况下的常量值。

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

enum TYPE { INTEGER, DOUBLE, INVALID };

#define typename(x) \
  _Generic((x), int: INTEGER, double: DOUBLE, default: INVALID)

typedef void (*FuncPtr)();

void printInt(int x) { printf("printed from printInt: %d\n", x); }

void printDouble(double x) { printf("printed from printDouble: %f\n", x); }

int main() {
  int input1 = 10233;
  double input2 = 11.234;

  FuncPtr func_ptrs[] = {printInt, printDouble};

  switch (typename(input1)) {
    case INTEGER:
      func_ptrs[INTEGER](input1);
      break;
    case DOUBLE:
      func_ptrs[DOUBLE](input1);
      break;
    case INVALID:
      printf("No corresponding type found!\n");
    default:
      break;
  }

  switch (typename(input2)) {
    case INTEGER:
      func_ptrs[INTEGER](input2);
      break;
    case DOUBLE:
      func_ptrs[DOUBLE](input2);
      break;
    case INVALID:
      printf("No corresponding type found!\n");
    default:
      break;
  }

  exit(EXIT_SUCCESS);
}

输出:

printed from printInt: 10233
printed from printDouble: 11.234000
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook

相关文章 - C Pointer