函数指针的 Typedef

我们可以使用 typedef 来简化函数指针的使用。想象一下,我们有一些函数,都具有相同的签名,使用他们的参数以不同的方式打印出来:

#include<stdio.h>

void print_to_n(int n)
{
    for (int i = 1; i <= n; ++i)
        printf("%d\n", i);
}

void print_n(int n)
{
    printf("%d\n, n);
}

现在我们可以使用 typedef 来创建一个名为 printer 的命名函数指针类型:

typedef void (*printer_t)(int);

这将创建一个名为 printer_t 的类型,用于指向函数的指针,该函数接受单个 int 参数并且不返回任何内容,这与我们上面的函数的签名相匹配。要使用它,我们创建一个创建类型的变量,并为其指定一个有问题的函数:

printer_t p = &print_to_n;
void (*p)(int) = &print_to_n; // This would be required without the type

然后调用函数指针变量指向的函数:

p(5);           // Prints 1 2 3 4 5 on separate lines
(*p)(5);        // So does this

因此,typedef 在处理函数指针时允许更简单的语法。当函数指针用于更复杂的情况时,例如函数的参数,这一点就变得更加明显。

如果你使用的函数将函数指针作为参数而未定义函数指针类型,则函数定义将是,

void foo (void (*printer)(int), int y){
    //code
    printer(y);
    //code
}

但是,使用 typedef 它是:

void foo (printer_t printer, int y){
    //code
    printer(y);
    //code
}

同样,函数可以返回函数指针,并且再次使用 typedef 可以使语法更简单。

一个典型的例子是 <signal.h>signal 功能。它的声明(来自 C 标准)是:

void (*signal(int sig, void (*func)(int)))(int);

这是一个带有两个参数的函数 - 一个 int 和一个指向函数的指针,该函数将 int 作为参数并且不返回任何内容 - 并返回一个指向函数的指针,就像它的第二个参数一样。

如果我们将类型 SigCatcher 定义为指向函数类型的指针的别名:

typedef void (*SigCatcher)(int);

然后我们可以使用以下方式声明 signal()

SigCatcher signal(int sig, SigCatcher func);

总的来说,这更容易理解(即使 C 标准没有选择定义类型来完成工作)。signal 函数有两个参数,一个 int 和一个 SigCatcher,它返回一个 SigCatcher - 其中 SigCatcher 是一个指向一个函数的指针,该函数接受一个 int 参数并且什么都不返回。

虽然使用 typedef 名称作为指向函数类型的指针可以使生活更轻松,但它也可能导致后来维护代码的其他人感到困惑,因此请谨慎使用并使用适当的文档。另请参见功能指针