🌀 函数指针 

数组指针是指向数组的指针

函数指针是指向函数的指针,存放函数地址的指针。

那么 & 地址函数名,取出的就是函数的地址。

从这里我们就联想到了 数组名 != &数组名,那么函数也是这样的吗?

答案:不是!函数名 == &函数名(完全等价)

示例,如下代码所示 👇

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int add(int x,int y)
{
return x + y;
}
int main(void)
{
int a = 10;
int b = 20;
add(a,b);
printf("&函数名 - %p\n",&add);
printf(" 函数名 - %p\n",add);
return 0;
}

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针数组

编译运行结果如下 👇 

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_数组_02

由此,证明了 函数名 == &函数名(完全等价)

那么指针所指向的类型就是函数返回值当中的类型。

当然,函数的地址也是可以取&出来,赋值给函数指针变量。

格式:函数返回值(*指针变量)(函数参数类型)

💥注意:这个函数指针变量是因为我们存放的地址是函数!

接着上面代码,示例,如下代码所示 👇

int (*ptr)(int,int) = &add;

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_数组_03

这里的 ptr 就是函数指针变量。 

那么这里 ptr 相当于存放函数的地址,如果我对 ptr 进行解引用的话就相当于找到了函数的地址。而找到这个函数我们需要把 (*ptr) 用小括号给括起来。调用的时候进行传参,所以需要在后面给上()

示例,如下代码所示 👇

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int add(int x,int y)
{
return x + y;
}
int main(void)
{
int (*ptr)(int, int) = &add;
int ret = (*ptr)(3, 5);
printf("ret = %d\n", ret);
return 0;
}

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针_04

编译运行结果👉  ret  =  8

从上述代码中可以说明调用时✔的,木的问题。这个地方用的就是函数指针,用了一个函数指针去调用它所指向的函数。

int (*ptr)(int, int) = add;

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针_05

当然,你这样子也是和上面是等价的。 

int ret = ptr(3, 5);

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_数组_06

以及这样子也都是没有问题的,运行结果都是一样的。 

函数指针的应用

拓展示例如下👇


💥 函数指针数组 

说函数指针数组的时候,先让我们来回顾下整形指针数组。

int* arr[5];

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针数组_07

这是整形指针数组就是这里面存放的都是整形指针。 

那么函数指针数组  —  就是存放函数指针的数组

示例,如下代码所示 👇

#include<stdio.h>
int add(int x, int y)
{
return x + y;
}
int sub(int x, int y)
{
return x - y;
}
int main(void)
{
int(*p1)(int, int) = &add;
int(*p2)(int, int) = ⊂
int(*Funtwo[2])(int, int) = { add, sub };//(13)
return 0;
}

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针数组_08

int(*Funtwo[2])(int, int) = { add, sub };

int(*Funtwo[2])(int, int) = { &add, &sub };

这两种写法都是一样的、取地址和不取地址、在函数都是一样的。

解释上述代码👆Funtwo首先和 [ ] 进行结合,和 [ ] 结合的时候就说明是个数组,数组是具有两个元素。那么当 Funtow[2] 被去掉的时候,剩下的就是函数指针了,int (*)(int,int); 加[2]是因为只是打算放入两个函数进去,那么③个④个都是一样以此类推......(13)

然后,就是对数组进行初始化。放入相应的函数进去即可!上述代码当中就放入了add、sub函数。

💥重点核心:函数指针数组里面就可以存放同类型的函数指针! (数据类型同、且能存放多个)

🔥 函数指针数组应用 

其实主要实现在当你创建的函数过多的时候,可以用函数指针数组来进行接收进行初始化。

例如假设你有多个函数的时候,当然单个函数也行。就假设你有多个函数的时候。

示例,如下代码所示 👇

int(*pa[4])(int,int) = {max1,max2,max3,max4};

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针_09

那么就可以用函数指针对应的下标来存放多少的函数的地址了,其实和指针数组特别类似。 


💥 指向函数指针数组指针 

指向函数指针数组的指针是一共指针指针指向一共数组,数组的元素都是函数指针

函数指针的数组本质上是数组,取出函数指针数组的地址

整形数组,示例,如下代码所示 👇

int arr[3];
int(*pa1)[3] = &arr;

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针_10

整形指针数组,示例,如下代码所示 👇 

int* arr[2];
int*(*pa2)[2] = &arr;

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针数组_11

💥注意:在这里 pa2 是一个指向 整形指针数组 的指针!

那么接下来来说说函数指针数组 指针,示例,如下代码所示 👇

int (*p1)(int,int);//函数指针
int (*p2[5])(int,int);//函数指针数组

int(*(*p3)[5])(int,int) = &p2;//取出的是函数指针数组的地址

【C语言】进阶指针Ⅳ 函数指针、函数指针数组、函数指针数组应用、指向函数指针数组指针。_函数指针_12

p3 就是一个指向 函数指针的数组 的 指针!

这里无非就是在p3加了个指针,然后用小括号括起来。之所以要用小括号,因为p3 会和 [ ] 进行结合。那么把 (*p3)[5] 去掉的话不就是函数指针了吗?你再一看(*p3)[5]不其实也是一个数组指针🤔

当然指向函数指针数组的指针这个东西知道就可以了,最主要的是去理解,不必深究,不然你将越套越深(doge)