C/C++ 函数指针

函数指针是一个指向函数地址的指针,未来可以通过函数指针来调用函数。可以把函数指针的定义理解为一种协议代理机制。函数指针定义了函数应该长什么样,需要什么参数,会得到何种返回值。这就相当于定义了一个协议。不同的代理人根据这一层协议,去实现自己的函数体,也即实现自己的代理行为。不同的代理人可以把自己的函数体传递给函数指针的调用者,调用者并不关心是谁代理了这个协议,只要传递给他的是一个合法的非空指针的协议,就可以在合适的时机去执行这个函数体。从这个意义上来说,函数指针的一大好处就是封装了行为。

那么,函数指针具体是如何定义的,调用者是如何调用函数指针传进来的函数体的?这篇文章就通过几个例子来说明函数指针的用法。

函数指针最基本的用法如下:

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;
}

留下评论