函数指针是C语言的灵魂之一,基于C语言实现的面向对象,底层都以函数指针为基础。

函数指针的定义

C语言中,可以通过以下方式定义函数指针:

type (*fn)(args)

其中,fn为指针变量名,type为指针所指向的函数的返回值类型,args为指针所指向的函数的参数列表。可以通过&运算符对函数指针赋值,通过(*fn)()的方式调用。举例:

int (*fn)(int a);

int func(int a) {
    printf("call func, arg a = %d\n", a);
    return a;
}

int main(int argc, char **argv) {
    fn = &func;
    (*fn)(10);
    return 0;
}

参数和返回值类型共同决定函数指针的类型,不同类型的函数指针之间不能做类型转换。

函数指针数组

指针数组

int *p[10];

在这条C语言语句中,由于[]运算符的优先级高于*运算符,因此p是一个有10个元素的数组,再结合*,可知数组p中的每一个元素的类型都是int型指针。上述声明等价于:

int *(p[10]);

数组指针

int (*p)[10];

在这条C语言语句中,首先,p是一个指针,接着,p是一个指向数组的指针,并且数组中每一个元素的类型都是int。

函数指针数组

函数指针数组的定义同普通指针数组的定义相同。

int (*fn[10])(args);

这样就定义了一个有10个元素的指针数组,其中,每个指针都是一个函数指针,指向一个返回值类型为 int,参数为 args 的函数。

返回指针的函数

C语言中,可以将函数的返回值类型定义为指针,具体做法例如:

int * (*fn)(args);

这样便定义了一个返回值类型为int型指针,参数为args的函数指针。

返回数组指针的函数

C语言中,函数的返回值类型可以是指向数组的指针。例如:

int (*fn(args))[];
int (*fu(args))[] {
   
}

这样,fn便是一个返回数组指针的函数,该数组指针指向一个有5个int型元素的数组。

复杂指针嵌套语句的解读

C语言中所有复杂的指针声明都是由各种声明嵌套构成的。左右法则是一个从C标准中归纳出来的解读复杂指针声明的方法。

左右法则:首先从最里面的未定义标识符开始,然后往右看,再往左看。每当遇到圆括号时,就掉转阅读方向。一旦解析玩圆括号里面所有的内容,就跳出圆括号。重复这一过程直至整个声明解析完毕。

举例:

int (*(*func)(int *p))[5];

首先,func是一个函数指针,指向一个参数为int *p的函数,函数的返回值类型为指向数组的指针,该数组具有5个int型的元素。

再如下例:

int (*(*fn)(args))[5];

这便定义了一个函数指针,指向的函数返回一个数组指针,该数组指针指向一个有5个int类型的元素的数组。

typedef与函数指针

在C语言中,typedef用作类型定义。建立一个类型别名的方法如下:

在传统的变量声明表达式中用类型名替代变量名,然后把typedef关键字加在该语句的开头。

例如:

typedef int* (*A[5])(int, char **);
A a[5];

int* (*a[5])(int, char **);

是等价的。

其他的更简单的使用typedef的语句如:

typedef long long ll;
typedef char * pchar;

也就容易理解了。

函数指针作为参数

将函数指针类型作为参数进行传参时,函数名前加不加&符号都可以。