先看三个函数
const double * f1(const double ar[], int n);
const double * f2(const double [], int);
const double * f3(const double *, int);
这三个函数意思一样,都是定义一个函数,第一个参数是一个double数组,第二个参数是一个int变量,返回类型都是 double *。唯一的区别是函数名不一样,所以函数地址也不同。
按指针函数定义,如果定义一个指针表示函数f1,则为:
const double * (*p1)(const double *, int);
指向f1:
const double * (*p1)(const double *, int) = f1;
这一大串符号中,变量只有p1,其余的都是修饰符,所以如果使用自动变量:
auto p2=f2;
可以很明显看出来,p1分别是f1的地址(指针),但是在调用函数的时候*p1和p1是一样的;而p2就是f2.
cout << (*p1)(av, 3) << “: ” << *(*p1)(av, 3) << endl;
cout << p1(av, 3) << “: ” << *p1(av, 3) << endl;
cout << p2(av, 3) << “: ” << *p2(av, 3) << endl;
这三个输出,*p1等同于f1,由于f1返回类型是double *,所以输出的是f1()返回值的地址,加*之后输出的就是返回值;
p1虽然是f1的地址,但是在函数调用的时候,两者等同,所以输出与1相同,要想输出函数f1()的地址,需要&p1;
p2是自动变量,等同于f2,直接输出的是函数f2()返回值的地址(指针),加*之后输出的就是函数返回值;但是&p2输出的时函数地址,而&f2输出结果是1,这样子看是*p2等同于f2。
函数指针数组
const double * (*pa[3])(const double *, int) = {f1, f2, f3};
首先看优先级,[]最高,所以可以变为:
const double * (* (pa[3]))(const double *, int) = {f1, f2, f3};
这样子就好看了,类似于数组的定义,当pa[0]=f1,pa[2]=f2,pa[3]=f3的时候,定义的时候就是double pa[3]={f1, f2, f3}.再把前面那些修饰符加上,就是函数指针数组的定义加初始化。再解释就方便了,pa是个数组,数组有三个元素,三个元素分别指向f1,f2,f3,拆开看跟之前的单个定义一样(比如pa[0]等价于p1)。
这里数组初始化的时候不能使用自动变量,但是可以这样:
autp pb=pa;
因为自动变量只能用于单个数值初始化,pa就是单个数值,数组pa的首元素的地址。
函数调用
const double * px = pa[0](av, 3);
const double * py = (*pb[1])(av, 3);
或者
double x = *pa[0](av, 3);
double y = *(*pb[1])(av, 3);
注意定义类型要对应,double *对应pa[0](av, 3)(同*pa[0](av, 3)),double 对应 *pa[0](av, 3)(同*(*pa[0])(av, 3)).
指向数组pa的指针
auto pc=&pa;
pc是数组pa的地址,这样子最简单。
指针数组定义:
*pd[3]; // 一个普通数组,元素是三个指针类型
(*pd)[3]; // 一个指针数组,元素是三个XX类型
所以用*pd替换pa,就得到:
const double * (*(*pd)[3])(const double *, int) = &pa;
pd是个指向数组的指针,(*pd)这个数组的每一个元素是个指向函数的指针,(*(*pd)[x])这些函数是指针函数,特别的,这些函数的返回值也是指针。