目录
1.函数指针
- 数组指针:指向数组的指针
- 函数指针:指向函数的指针(存放函数地址的指针)
- 数组arr:arr是首元素地址,&arr是整个数组地址
- 函数没有首元素的概念,所以函数名和&函数名都是函数的地址
2.函数类型
首先看一下数组指针:int arr[10];
- 怎么存储&arr,整个数组的地址呢
- 首先&arr说明是个地址,地址就需要指针存储,所以是*p
- 然后,arr是个数组,说明p指向的是个数组,数组arr10个元素,所以(*p)[10],[]比*的优先级别高
- 最后,arr里面每个元素int类型,所以数组指针的写法是int (*p)[10]
- 数组指针类型就是去掉变量名p,int (*)[10]
所以函数存储:int (*p)(int,int) = ADD;
- 因为函数地址,需要指针接收 *p
- 看到(),代表是个函数,p指向一个函数
- 函数参数类型是int,int(int x ,int y也可以,但是这里只要说明函数形参参数的类型就行,没必要写形参)
- 最后看函数的返回类型是int
- 函数指针类型:int (*)(int,int)
- 程序也可以说明,&函数名和函数名没区别,都是函数的地址
- *p1 找到ADD函数
3. 看几个代码
练习
- fun1 ✔
- fun2 ❌
- 因为()比 * 的优先级高
代码分析1
- (*): 说明是个指针
- void (*)():说明是个函数指针,没有参数,且返回值为void,没有返回值
- (类型)------> 强制类型转换
- ( void (*)() ) 0: 将一个整数0强制转换成函数指针类型,意味着把0当作一个函数地址。没有参数,且返回值为void,没有返回值
- (* ( void (*)() ) 0 )(): * 找到这个函数,没有参数,返回值void的函数
代码分析2
- signal() :说明signal一个函数
- signal( int,void(*)(int) ):第一个参数为int类型,第二个参数是函数指针类型(没有参数,且返回值为void)
- 将整个代码去掉上面一行后为 void (*)(int) :说明整个signal函数的返回类型是一个函数指针,参数是int,返回值值void
- 类似于这种形式
- 但上面图片这种写法是错误的,signal返回类型是一个函数指针,那么*就要靠着signal
利用typedef优化一下:
- 将函数指针类型重新定义不能按照传统的写法
- 要写成这种形式
- 所以将之前的代码优化为
4.函数的解引用
- 这里我们第一个*p找到函数ADD
- 那为什么**p和***p都能找到ADD呢?
- 答案:* 在这里不起作用
简单分析:
int (*p)(int,int) = ADD或者&ADD;
当&ADD的时候,*p就找到ADD这个函数。所以*p是等价于ADD的。所以(*p)(2,3) == ADD(2,3)
而之前说了&ADD和ADD没有区别,那么说明p和ADD也就没区别,类似于一维数组,见下图。所以p(2,3) == ADD(2,3)
总之就是:
&地址,就要*找到它 int (*p)(int,int) = &ADD------>(*p)==ADD
如果直接 地址,那么就不需要*去找它 int (*p)(int,int) = ADD------>p==ADD
5.函数指针数组
- parr[4] :说明是个数组,有四个元素
- int (*)(int,int):函数指针类型,说明parr是个函数指针数组
正确使用:
6.练习
- 第一个是函数指针数组:parr1先和[]结合是数组,有10个元素。每个元素都是函数指针,无参数,返回值int类型
- 第二个瞎写的(❌)
- 第三个和第一个一样,但是我们说,不能这样写,parr3[10]要放到*的后面(❌)
练习一下: