这里仅讨论数组函数相关的复杂类型的简化。

一、用typedef简化复杂类型声明

嵌在对象定义中的隐式类型不容易认读,因此我们可以用typedef来简化类型声明。

typedef在定义类型而不是对象!

1) 简化数组类型

typedef int arr_t[10];

解读步骤如下:

  1. 找到typedef中的新名字。

    这里的新名字是arr_t。这是一种新的类型名

  2. 找到arr_t附近的修饰符。

    arr_t左侧没有修饰符,右侧有[]。这样,arr_t就是一个数组类型

  3. 去掉名字。

    剩下的是:

    int [10]

    这就是新类型arr_t的代表的已有类型。很明显,这是一种数组类型。

  4. 得出结论

    综上,类型arr_t就是一个数组类型;这种类型的数组具有这样的特征:

    • 是一维的
    • 长度为10。
    • 基类型为int
  5. 应用

     arr_t a; //等价于:int a[10];
    

2) 简化函数类型

typedef int fn_t(int);

解读步骤如下:

  1. 找到typedef中的新名字。

    这里的新名字是fn_t。这是一种新的类型名

  2. 找到fn_t附近的修饰符。

    fn_t左侧没有修饰符,右侧有()。这样,fn_t就是一个函数类型

  3. 去掉名字。

    剩下的是:

    int (int)

    这就是函数类型fn_t的代表的已有类型。很明显,这是一种函数类型。

  4. 得出结论

    综上,类型fn_t就是一个函数类型;这种类型的函数签名具有这样的特征:

    • 带有一个参数,这个参数的类型是int
    • 函数返回值类型为int
  5. 应用

    C/C++规定,不能定义函数类型的对象。函数类型只能作为函数的参数类型。

     int f(int x, fn_t fn); //参数fn的类型是函数
    

3) 简化函数指针类型

typedef int (*pf_t)(int);

解读步骤如下:

  1. 找到typedef中的新名字。

    这里的新名字是pf_t。这是一种新的类型名

  2. 找到pf_t附近的修饰符。

    pf_t左侧有修饰符*,并且和pf_t一起括在()中。这对()提升了*的优先级,因此*先和pf_t结合。这样,无论如何,pf_t就是一个指针类型

  3. 去掉名字及其就近的修饰符。 剩下的是:
    int (int)

    这就是指针类型pf_t的基类型。很明显,这是一种函数类型。

  4. 得出结论

    综上,类型pf_t就是一个指向函数指针类型;这种类型的指针指向的函数签名具有这样的特征:

    • 带有一个参数,这个参数的类型是int
    • 函数返回值类型为int
  5. 应用

    可以定义函数指针类型的对象。

     int g(int x) {...}
     pf_t pf;
     pf = g;
     pf(2); 
    

    函数指针类型也常作为函数的参数类型。

     int f(int x, pf_t fn); //参数fn的类型是函数指针类型,fn是指向函数的指针
    

4) 函数类型参数和函数指针类型参数是等效的

以下两个函数的签名是等效的:

int f(int x, fn_t fn); //fn是函数
int f(int x, pf_t fn); //fn是函数指针

二、C++的using语句

C++的using语句可以替代typedef语句,并且可读性更强。例如:

using arr_t = int [10];
using fn_t = int (int);
using pf_t = int (*)(int);

三、更复杂的案例

如果有定义:

int (*a(int))(int);

那么名字a是什么呢?

解读步骤:

  1. 找到a附近的修饰符。

    前后有*()。由于()的优先级更高,因此a首先和()结合。因此,a一定是个函数。很明显,这个函数带有一个整型参数。

  2. 去掉a(int),剩下的是int (*)(int)

    这是函数a的返回值类型。很明显,这是一种指向函数的指针类型

  3. 总结

    综上,函数a的特征是:

    • 带有一个整型参数
    • 返回函数指针
  4. 使用

     a(1)(2); //用参数1调用a(),返回函数指针;再调用函数指针指向的函数,参数为2
    
  5. 简化

    显然,函数a的类型非常复杂,不好认读。因此最好简化。

     typedef int (*pf_t)(int); //C
     //using pf_t = int (*)(int); //C++
     pf_t a(int);
    

    以下是完整的示例程序。

     #include <stdio.h>
    
     int f(int x) {
         printf("f: %d\n", x);
     }
    
     int (*a(int i))(int) {
         printf("a: %d\n", i);
         return f;
     }
    
     int main() {
         a(1)(2);
    
         return 0;
     }
    

    结果是:

     a: 1
     f: 2