指针进阶(二)(上)

简介: 指针进阶(二)(上)

函数指针数组


数组是一个存放相同类型数据的存储空间,前面博主已经讲解了指针数组, 比如

 

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. //          );

相关文章
|
9月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
9月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
105 0
|
9月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
9月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
9月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
9月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
69 4
|
9月前
指针进阶(3)
指针进阶(3)
62 1
|
9月前
|
C++
指针进阶(1)
指针进阶(1)
59 1
|
9月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
80 2
|
10月前
|
C语言
C语言进阶:进阶指针(下)
C语言进阶:进阶指针(下)
57 2