探讨函数指针

在C++/C中,函数的函数名本身就是地址,而函数指针就是存储这个地址的变量。如下代码

void fun(int a, int b) {.....};

fun就是一个地址,而void (*p)(int, int) = fun;就是指向这个函数的指针,其实说来p函数指针这时也使指向这个函数的,所以要使用这个函数的话,理论上应该写成(*p)(2, 3);这种形式,但是实际上,通过p(2, 3)也可以成功调用,所以我们可以把函数指针在某种情况下当成函数的别名,虽然这样不符合逻辑,当然,如果你比较较真,可以使用(*p)(2, 3);

现在来总结下关于函数指针的一些知识点:

1.声明特定类型的函数指针

1.先写出要声明的指定函数的原型prototype。如void fun(int , int );
2.把prototype中的函数名替换成(*p),如void (*p)(int , int );
经过上面两步,你就声明了一个指向无返回值,带有两个int类型的函数的函数指针p。此时你可能会问,怎么调用啊?首先你要给他赋值,其次,调用分两种,就是上面一开始说的那两种。说白了,也就是对于函数指针调用函数,你可以解引用,也可以直接用地址。

2.声明特定类型的函数指针数组

1.和知识点一1,2步一样,我们先写出一个。第二步在想办法写成一个数组
2.把(*p)替换成(*p[3])这样p就是一个包含3个函数指针的数组。也就是说p是函数指针的指针!
指针的指针说白了p是指向数组的第一个元素。也就是说p的地址值是第一个元素的地址,所以说p是函数指针的指针,因为p指向的时函数指针,函数指针指向的才是内存中函数指令区域的那个块

下面来具体练习一下:

假设有const double * (*pa[3])(const double * , int ) = {f1, f2, f3},声明指向该函数指针数组的指针

C++11方法:auto pc = &pa;。这个方法十分简单方便,但是如果不支持C++11,我们就要用最原始的方法
分析:因为我们要声明的时一个指针,而不是一个数组所以首先用(*pd)把其扩起来,然后其是指向一个函数指针数组,这个数组有3个元素。所以其核心部分就是(*pd)[3],此时的意思就是所pd是一个指针,其指向包含3个元素的数组。所以我们要说明数组元素的类型,类型就是const double * (*)(const double *, int),也就是const double * (* (*pd)[3])(const double *, int)。

可能有人看不懂,我举个例子,
1.int *p;p的类型是int *,
2.而int *p[3],p的类型是int *[3],也很好理解就是带有三个数组,元素类型都是int *。
3.而int (*p[3])(int ),p的类型是int (*[3])(int),p是指向一个3个元素的数组,且每个元素的类型都是int (*)(int)。
(指针是什么类型主要看括号、*号、[]号,和参数列表的结合顺序,如果只有(*p)(int ,....)那p就是函数指针)
所以有以下推论:     
要判断数组或指针的类型,就是拿掉<数组名、指针名>后组成的,而且[]和*是从右向左结合
要判断数组元素的类型,就是在数组类型的基础上把大小拿掉

这么多东西,是不是有点折腾烦了……我们来点正常人用的,使用typedef创建函数指针类型别名:

typedef简化函数指针其本质就是为函数指针的类型取别名。
如下:
typedef const double *(*p_fun)(const double *, int);

其是此时相当于 typedef Const double *(*)(const double *, int)  p_fun;
当然你不能这样写,这样写只是方便理解。现在p_fun不是函数指针了,而是这种函数指针类型的别名,所以此时你可以这样做:

p_fun p1 = f1;
p_fun pa[3] = {f1, f2, f3};
p_fun (*pd)[3] = &pa;

是不是比之前的简单许多!

猜你喜欢

转载自blog.csdn.net/FYZDMMCpp/article/details/51182941