备案 网站名,wordpress 页面模板,网站备案和域名解析,百度免费云服务器继续上次的指针#xff0c;想起来还有指针的内容还没有更新完#xff0c;今天来补上之前的内容#xff0c;上次我们讲了函数指针#xff0c;并且使用它来实现一些功能#xff0c;今天我们就讲一讲函数指针数组等内容#xff0c;废话不多说#xff0c;我们开始今天的学习… 继续上次的指针想起来还有指针的内容还没有更新完今天来补上之前的内容上次我们讲了函数指针并且使用它来实现一些功能今天我们就讲一讲函数指针数组等内容废话不多说我们开始今天的学习吧。
函数指针数组 在引出函数指针的时候我们会先引出字符指针还有整型指针那同样的道理函数指针数组是什么我们可能还是比较陌生但是如果是字符指针数组还有整型指针数组我们可能听起来不是特别陌生。 那再讲之前我给大家先讲一下函数指针函数指针是啥呢函数指针竟然是指针那就是来存放函数的地址的那我们先写一个简单的函数然后来存放它的地址。
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);return 0;
}我们可以发现打印出来的两个地址都是同一个地址所以表示两个方式都可以取出函数的地址 在这里我们可以看到我们的地址是一样的那我们要存放他们的地址改怎么写呢
我们来看看
#includestdio.h
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);int (*pf)(int, int) Add;return 0;
}这样我们就可以把它函数的地址写出来这和那个数组指针也特别相似取出的数组地址也是这样的。 因为时间太长我帮大家在回忆一下我们的数组指针比如我们现在要取出的是数组的地址我们改怎么表示让我们来看一看吧。
int main()
{int arr[] { 1,2,3,4,5,6 };int(*pa)[6] arr;return 0;
}在这里我们可以看到的是数组指针是指向数组地址的指针可以看到它的格式其实和函数指针的差不多。 那我们的函数指针有什么用呢答案是可以调用这个函数比如就我们上面的Add函数我们来看代码。
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);int (*pf)(int, int) Add;return 0;
}我们可以这样写
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);int (*pf)(int, int) Add;int ret (*pf)(3, 5);printf(%d\n, ret);return 0;
}在这里其实可以不写意思就是int ret (*pf)(3, 5);可以写成int ret pf(3, 5);其实这两个的结果是一样的或者说就算我们加很多也不影响我们的结果来看看吧
int Add(int x, int y)
{return x y;
}
int main()
{printf(%p\n, Add);printf(%p\n, Add);int (*pf)(int, int) Add;int ret (*pf)(3, 5);printf(%d\n, ret);ret printf(%d\n, (*********pf)(4, 6));return 0;
}写了这么多主要是为了后面做铺垫那我们现在才来讲我们的函数指针数组 数组是什么我们之前见过字符指针数组他是来存放字符指针我们也讲过整型指针数组它是来存放整型指针的数组那同样函数指针数组就是来存放函数指针的我们来举个列子 int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}int main()
{int (*pf1)(int, int) Add;int (*pf2)(int, int) Sub;int (*pf3)(int, int) Mul;int (*pf4)(int, int) Div;return 0;
}我们首先看到这么多的函数他们的功能类似我们的计算器这里就只写了加减乘除的功能通过我们的代码我们可以看到的是四个一样的函数指针那我们是不能就可以用数组的形似来存放它们。因为数组是不是能存放多个类型相同的元素。 那我们就可以来写一写看
int main()
{int (*pf1)(int, int) Add;int (*pf2)(int, int) Sub;int (*pf3)(int, int) Mul;int (*pf4)(int, int) Div;int(*pfarr[4])(int, int) { Add,Sub,Mul,Div };//pfarr就是存放函数指针的数组return 0;
}那函数指针数组难道就是一个摆设吗不它还是有一点作用的那它的作用是什么呢让我们来一起看看吧。 我们是不是就可以用它来实现一个计算器我们来设计一个吧
int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void menu()
{printf(***1.Add 2.Sub ****\n);printf(***3.Mul 4.Div ****\n);printf(****0.exit ****\n);printf(********************\n);
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d ,input);switch (input){case 0:printf(退出计算器\n);break;case 1:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Add(x, y);printf(ret %d\n, ret);break;case 2:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Sub(x, y);printf(ret %d\n, ret);break;case 3:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Mul(x, y);printf(ret %d\n, ret);break;case 4:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Div(x, y);printf(ret %d\n, ret);break;default:printf(选择错误请重新选择\n);break;}} while (input);return 0;}虽然我们实现一个简单的计算器但是其实我们的代码看起来并不是特别好看反而有点冗余重复的内容有点多而且如果我们加一些其他的运算的时候函数会变得越来越长那我们该怎么改改让我们的代码看起来又好看又实用呢这个时候我们就可以用函数指针数组进行改正现在我们来对它进行整改。
我们用这个的时候之前一定要注意的问题是计算器这个函数的类型是一样的否则其他的话就不行了。
int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void menu()
{printf(***1.Add 2.Sub ****\n);printf(***3.Mul 4.Div ****\n);printf(****0.exit ****\n);printf(********************\n);
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d, input);int (*pf[5])(int, int) { NULL,Add,Sub,Mul,Div };if (input 0){printf(退出计算器\n);}else if (input 1 input 4){printf(请输入两个操作数 :);scanf(%d %d, x, y);ret pf[input](x, y);printf(%d\n, ret);}} while (input);return 0;}这样也能实现我们计算器的效果而且好处也是特别大首先解决了我们的代码冗余的现象其次是我们如果想加入其他的运算也可以直接加入只要改一下数组的大小并把函数的地址放到里面就可以解决问题其实很简单。我们也将这个东西叫做转移表这就是我们函数数组指针应用但是这只是一个例子其他还有很多的作用这里就不扩展了。
指向函数指针数组的指针
一看这个标题不知道大家头是不是大了反正小编一开始看这个有点云里雾里的感觉但是经过一段时间的学习发现它也就这啊那现在我们开始举列子。
int a 10;
int b 20;
int c 30;
int* arr[] { a,b,c };//整型指针数组我们先来看简单的然后慢慢的引入先是整型指针数组那如果是这样的一个问题要指向整型指针数组的指针我们该怎么写
int* (*parr)[3] arr;这就是指向整型指针数组的指针同样的道理我们来看指向函数指针数组的指针。
int (*pf[5])(int, int) { NULL,Add,Sub,Mul,Div };int(*(*ppf)[5])(int, int) pf;我们就拿计算器的来写就是这个样子的。 但是这个其实不用理解太深稍微了解一下就知道了不是特别重要。
回调函数 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针地址作为参数传递给另一个 函数当这个指针被用来调用其所指向的函数时我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用而是在特定的事件或条件发生时由另外的一方调用的用于对该事件或条件进 行响应。 什么意思呢就是假设我们有两个函数一个函数叫A一个函数叫B我们B函数的参数是A函数的地址我们在B函数里使用这个函数A。 今天就讲一个例子还是我们的计算器下次给大家讲一个qsort这也叫快速排序让大家更好的理解我们的内容。
先把我们的计算器在拿出来给大家看一下
int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void menu()
{printf(***1.Add 2.Sub ****\n);printf(***3.Mul 4.Div ****\n);printf(****0.exit ****\n);printf(********************\n);
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d ,input);switch (input){case 0:printf(退出计算器\n);break;case 1:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Add(x, y);printf(ret %d\n, ret);break;case 2:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Sub(x, y);printf(ret %d\n, ret);break;case 3:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Mul(x, y);printf(ret %d\n, ret);break;case 4:printf(请输入两个操作数 :);scanf(%d %d, x, y);ret Div(x, y);printf(ret %d\n, ret);break;default:break;}} while (input);return 0;}
我们可以把相同的部分也就是case语句分装成一个函数的思路去实现
我们可以看到我们的代码哪里是不太一样的地方其实就是我们调用函数的地方如果我们能写一个函数calc来放这些函数的地址问题是不是解决了其实就是写成这个样子。
int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void menu()
{printf(***1.Add 2.Sub ****\n);printf(***3.Mul 4.Div ****\n);printf(****0.exit ****\n);printf(********************\n);
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d ,input);switch (input){case 0:printf(退出计算器\n);break;case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;default:break;}} while (input);return 0;}那现在要做的是什么就是完成我们的calc函数这样就可以实现计算器的功能
calc我们的返回类型就是void 函数他们的地址那我们是不是可以写成int (*pf)(int,int)。 int Add(int x, int y)
{return x y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void menu()
{printf(***1.Add 2.Sub ****\n);printf(***3.Mul 4.Div ****\n);printf(****0.exit ****\n);printf(********************\n);
}void calc(int (*pf)(int, int))
{int x 0;int y 0;int ret 0;printf(请输入两个操作数 :);scanf(%d %d, x, y);ret pf(x, y);printf(ret %d\n, ret);
}
int main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择);scanf(%d, input);switch (input){case 0:printf(退出计算器\n);break;case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;default:break;}} while (input);return 0;}这样就把之前的功能也实现了。我们后面再讲一个qsort今天懒得讲了摆烂ing
我们下次再见拜拜