函数指针是一个指向函数地址的指针,未来可以通过函数指针来调用函数。可以把函数指针的定义理解为一种协议代理机制。函数指针定义了函数应该长什么样,需要什么参数,会得到何种返回值。这就相当于定义了一个协议。不同的代理人根据这一层协议,去实现自己的函数体,也即实现自己的代理行为。不同的代理人可以把自己的函数体传递给函数指针的调用者,调用者并不关心是谁代理了这个协议,只要传递给他的是一个合法的非空指针的协议,就可以在合适的时机去执行这个函数体。从这个意义上来说,函数指针的一大好处就是封装了行为。
那么,函数指针具体是如何定义的,调用者是如何调用函数指针传进来的函数体的?这篇文章就通过几个例子来说明函数指针的用法。
函数指针最基本的用法如下:
void (*func_point)(int);
这就定义了一个名为 func_point
的函数指针,该函数指针接收一个 int
类型的参数,不返回任何值。我们来看一个完整的例子:
#include <stdio.h>
void foo(int x)
{
printf("%d\n", x);
}
int main()
{
void (*func_point)(int);
func_point = &foo;
func_point(3); // 第一种调用方式
(*func_point)(3); // 第二种调用方式
}
值得注意的是,这个例子定义了两种方式来调用函数指针。分别是
func_point(3);
和
(*func_point)(3);
两种调用方式都应该是比较好理解的。第一种方式是我们最熟知的方式,而第二种方式则与函数指针的定义方式一致。
复杂一点的是把函数指针当做参数传递给另一个函数,以及在一个函数中返回一个函数指针。具体的例子如下:
#include <stdio.h>
static void(*callback)(int) = 0;
// 函数指针作为输入参数
void set_callback(void(*func)(int))
{
callback = func;
}
// 函数指针作为返回值
void (*get_callback())(int)
{
return callback;
}
void foo(int x)
{
printf("%d\n", x);
}
int main()
{
set_callback(&foo); // 调用set_callback方法,传入foo函数指针
void(*my_callback)(int) = get_callback(); // 调用get_callback方法获得foo函数指针
if (my_callback != 0) {
my_callback(3);
}
}
先来看 set_callback
函数的定义
void set_callback(void(*func)(int))
{
callback = func;
}
set_callback
接收一个以 int
类型为输入参数且不返回值的函数指针类型,函数指针名为 func
。
再来看 get_callback
函数的定义。如果我们把 get_callback()
看成函数指针名,则 void (*get_callback())(int)
就是一个接收一个 int
类型输入参数且不返回值的函数指针,即 get_callback()
的返回类型就是一个 int
类型输入参数且不返回值的函数指针。
如果这两种定义让你感到困扰,可以通过 typedef
让函数指针的参数传递与值返回更符合一般的表达式。比如
#include <stdio.h>
typedef void (*callback_ptr)(int);
static callback_ptr callback = 0;
void set_callback(callback_ptr func)
{
callback = func;
}
callback_ptr get_callback()
{
return callback;
}