函数指针数组
数组是一个存放相同类型数据的存储空间,前面博主已经讲解了指针数组, 比如
1. int *arr[10]; 2. //数组的每个元素是int*
把函数的地址存到一个数组中,那这个数组就叫函数指针数组,下面时函数指针的数组的定义
int (*parr1[10])();
parr1 parr1 先和 [] 结合,说明 parr1是数组,数组的·内容是 int (*)() 类型的函数指针。
函数指针数组的用途: 转移表
接下来我将通过代码的形式来介绍一下函数指针的数组,这里博主编译一个简单的计算机进行讲解,代码如下
1. //int Add(int x, int y) 2. //{ 3. // return x + y; 4. //} 5. // 6. //int Sub(int x, int y) 7. //{ 8. // return x - y; 9. //} 10. // 11. //int Mul(int x, int y) 12. //{ 13. // return x * y; 14. //} 15. // 16. //int Div(int x, int y) 17. //{ 18. // return x / y; 19. //} 20. // 21. //void menu() 22. //{ 23. // printf("***************************\n"); 24. // printf("***** 1.add 2.sub ******\n"); 25. // printf("***** 3.mul 4.div ******\n"); 26. // printf("***** 0.exit ******\n"); 27. // printf("***************************\n"); 28. //} 29. //int main() 30. //{ 31. // int input = 0; 32. // int x = 0; 33. // int y = 0; 34. // int ret = 0; 35. // do 36. // { 37. // menu(); 38. // printf("请选择:>"); 39. // scanf("%d", &input); 40. // switch (input) 41. // { 42. // case 1: 43. // printf("请输入两个操作数:"); 44. // scanf("%d %d", &x, &y); 45. // ret = Add(x, y); 46. // printf("ret = %d\n", ret); 47. // break; 48. // case 2: 49. // printf("请输入两个操作数:"); 50. // scanf("%d %d", &x, &y); 51. // ret = Sub(x, y); 52. // printf("ret = %d\n", ret); 53. // break; 54. // case 3: 55. // printf("请输入两个操作数:"); 56. // scanf("%d %d", &x, &y); 57. // ret = Mul(x, y); 58. // printf("ret = %d\n", ret); 59. // break; 60. // case 4: 61. // printf("请输入两个操作数:"); 62. // scanf("%d %d", &x, &y); 63. // ret = Div(x, y); 64. // printf("ret = %d\n", ret); 65. // break; 66. // case 0: 67. // printf("退出计算器\n"); 68. // break; 69. // default: 70. // printf("选择错误,重新选择\n"); 71. // break; 72. // } 73. // } while (input); 74. // 75. // return 0; 76. //}
对于这段代码,我们发现这段代码有很多相同且类似的代码
1. printf("请输入两个操作数:"); 2. scanf("%d %d", &x, &y); 3. ret = Add(x, y); 4. printf("ret = %d\n", ret);
这就造成了冗余,那么有没有什么办法进行解决呢?其实我们这里就可以用函数指针组来进行解决
首先我们发现,我们所用的加减乘除函数,除了名字不同,参数与返回值都相同,是统一类型
数组的定义就是里面存放的为同一类型的数据
那么我们就可以进行使用,函数指针数组建立如下
1. int (* pfArr[5])(int, int) = {NULL, Add, Sub, Mul, Div}; 2. //数组的一个元素为NULL,是为了此程序在输入时方便
数组为pfArr;数组类型就为int(*)(int,int)
使用如下
1. int main() 2. //{ 3. // int input = 0; 4. // int x = 0; 5. // int y = 0; 6. // int ret = 0; 7. // //函数指针数组的使用 - 转移表 8. // int (* pfArr[5])(int, int) = {NULL, Add, Sub, Mul, Div}; 9. // // 0 1 2 3 4 10. // do 11. // { 12. // menu(); 13. // printf("请选择:>"); 14. // scanf("%d", &input); 15. // if (input >= 1 && input <= 4) 16. // { 17. // printf("请输入两个操作数:"); 18. // scanf("%d %d", &x, &y); 19. // ret = pfArr[input](x, y); 20. // printf("ret = %d\n", ret); 21. // } 22. // else if(input == 0) 23. // { 24. // printf("退出计算器\n"); 25. // } 26. // else 27. // { 28. // printf("选择错误,重新选择\n"); 29. // } 30. // } while (input); 31. // 32. // return 0;
指向函数指针数组的指针
大家想既然有函数指针数组,那么有没有指向函数指针数组的指针呢?
答案肯定是有的,指向函数指针数组的指针是一个 指针, 指针指向一个 数组 ,数组的元素都是 函数指针 ;
那我们该如何定义呢?定义如下
1. void test(const char* str) 2. { 3. printf("%s\n", str); 4. } 5. int main() 6. { 7. //函数指针pfun 8. void (*pfun)(const char*) = test; 9. //函数指针的数组pfunArr 10. void (*pfunArr[5])(const char* str); 11. pfunArr[0] = test; 12. //指向函数指针数组pfunArr的指针ppfunArr 13. void (*(*ppfunArr)[5])(const char*) = &pfunArr; 14. return 0; 15. }
回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
接下博主运用上面的简易计算器来实现一个回调函数
根据回调函数的定义,我们知道我们需要一个函数的指针为参数,传参后还要调用该指针所指向的函数
那我们首先先把函数作为指针并进行传参,这里博主创建以下函数代码
void Calc(int (*pf)(int, int))
此代码中Calc函数的参数就为函数指针,接下来我们就要满足传参后还要调用该函数,实现如下
1. //void Calc(int (*pf)(int, int)) 2. //{ 3. // int x = 0; 4. // int y = 0; 5. // int ret = 0; 6. // printf("请输入两个操作数:"); 7. // scanf("%d %d", &x, &y); 8. // ret = pf(x, y);\\进行调用 9. // printf("ret = %d\n", ret); 10. //}
那么就可以进行实现了,实现代码如下
1. //int main() 2. //{ 3. // int input = 0; 4. // int x = 0; 5. // int y = 0; 6. // int ret = 0; 7. // do 8. // { 9. // menu(); 10. // printf("请选择:>"); 11. // scanf("%d", &input); 12. // switch (input) 13. // { 14. // case 1: 15. // Calc(Add);//进行传参 16. // break; 17. // case 2: 18. // Calc(Sub); 19. // break; 20. // case 3: 21. // Calc(Mul); 22. // break; 23. // case 4: 24. // Calc(Div); 25. // break; 26. // case 0: 27. // printf("退出计算器\n"); 28. // break; 29. // default: 30. // printf("选择错误,重新选择\n"); 31. // break; 32. // } 33. // } while (input); 34. // 35. // return 0; 36. //}
回调函数逻辑如下
回调函数模拟实现qsort(快速排序)
博主在前面讲过冒泡排序,它可以将一个int型的数组里的数进行排序,但是就只能进行整数的排序,这里我们就引入了qsort函数,qsort函数为排序神器,搭配头文件#include<stlib.h>
我们来看一下这个函数的使用格式吧
void qsort(void* base,size_t num,size_t size,int (*cmp)(const void*, const void*));
里面这么多东西,那都是什么意思呢?解释如下
1. //void qsort(void* base, //指向了需要排序的数组的第一个元素 2. // size_t num, //排序的元素个数 3. // size_t size,//一个元素的大小,单位是字节 4. // int (*cmp)(const void*, const void*)//函数指针类型 - 这个函数指针指向的函数,能够比较base指向数组中的两个元素 5. // );