一个整活挑战:定义一个”指向函数的指针,该函数返回同类型的指针”,然后套 100 层。这个类型长这样(节选开头和结尾):

1
2
typedef long long int (* (* (* ... (* (*a)())(void) ... );
// 中间是 100 层重复的 (* ... () )

这是什么鬼类型

从变量名 a 出发,用”右左法则”读这个声明:

  1. a 先被 * 包住:a 是一个指针
  2. 右边跟 ():指针指向一个函数
  3. 函数返回值又在 (* ) 里:返回值还是指针
  4. 重复第 2、3 步 100 次

也就是:a 是一个函数指针,调用它返回下一个函数指针,再调用又返回下一个……一共 100 层

实现:自返回的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a fun()
{
static int i = 0;
printf("(%d)", ++i);
return (a)fun;
}

int main()
{
fun();
printf("\n");
fun()()()()/* ...省略 90 个... */()();
return 0;
}

fun 每次被调用就打印一个递增计数,然后把自己返回。于是 fun()()()()... 连续调用 100 次,屏幕上打出 (1)(2)(3)...(100)——每一层返回的函数指针正好是下一层要调用的。

意义

这个例子是理解复杂声明的最好练习:C 的声明语法围绕”使用形式”设计,指针、函数、数组可以无限组合。读复杂声明的钥匙是右左法则 + 从标识符出发,掌握了它,signalqsort 这类真实函数指针声明就不再可怕。

顺便:这个 typedef 是用脚本生成的 100 层,手写是不可能的。