我们都知道在 C 语言中,typedef
的作用是给已有的类型重新定义一个新的名字,今天在这里我们主要探讨一下使用 typedef
来简化函数指针的用法。
Example print
首先我们来看一个例子:
#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_t
的函数指针类型,如下:
typedef void (*printer_t)(int);
这个 typedef
创建了一个名叫 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
在处理函数指针时可以有一个更简单的语法形式,当使用环境很复杂时,这种 typedef
定义函数指针的方式会更加显眼。
接下来我们可以对比一下当我们想把一个函数指针当做一个参数时,使用 typedef
和不使用的区别:
- 不使用
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
后程序更简洁了,我们这样可以直接简便的返回函数指针。
Example signal
我们还可以看一个经典的例子。这个例子来自于 <signal.h>
,其中的声明如下:
void (*signal(int sig, void (*func)(int)))(int);
这是一个带有两个参数的函数:一个 int 和一个指向以 int 作为参数并且不返回任何内容的函数的指针,然后返回一个指向函数的指针,如同第二个参数。
如果我们将类型 SigCatcher 定义为函数类型指针的别名:
typedef void (*SigCatcher)(int);
then we could declare signal() using:
SigCatcher signal(int sig, SigCatcher func);
这样的话更方便我们理解。signal 函数采用两个参数,即 int 和 SigCatcher,并返回 SigCatcher:其中SigCatcher 是指向具有 int 参数且不返回任何内容的函数的指针。
注:尽管使用
typedef
名称来指向函数类型的指针使工作变得更轻松,但也可能导致其他人在以后维护您的代码时感到困惑,因此请谨慎使用并提供适当的文档。