C 语言中的函数指针
Jinku Hu
2023年10月12日
本文将介绍如何在 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 函数指针,尽管如此,printInt
和 printDouble
函数地址都存储在类型为 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