• 让学指针变得更简单(二)



    前言

    指针的深入学习(二)
    在这里插入图片描述


    一、函数指针数组

    数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,不懂的可以看我上一篇博客;让学指针变得更简单(一)
    比如:int* arr[10]; //数组的每个元素是int *
    那么我们对函数指针数组也好理解了,首先肯定是数组,其次数组元素类型是函数指针(地址);那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
    int (* parr1[10])();
    int * parr2 [10] ();
    int ( * )() parr3[10];
    看一下这三个,那个是函数指针数组?答案是:parr1 ,parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?是 int (*)() 类型的函数指针。注意数组名应该放进带 *的括号里,int ( *parr1[10])();所以第一个就是函数指针数组的样子了; 函数指针数组的用途:转移表;

    1.1函数指针的用途(上一篇博客中函数指针的用途)

    #include <stdio.h>
    int add(int a, int b)
    {
    return a + b;
    }
    int sub(int a, int b)
    {
    return a - b;
    }
    int mul(int a, int b)
    {
    return a*b;
    }
    int div(int a, int b)
    {
    return a / b;
    }
    int main()
    {
    int x, y;
    int input = 1;
      int ret = 0;
      do
     {
        printf( "*************************\n" );
        printf( " 1:add      2:sub \n" );
        printf( " 3:mul      4:div \n" );
        printf( "*************************\n" );
        printf( "请选择:" );
        scanf( "%d", &input);
        switch (input)
       {
       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;
        case 0:
            printf("退出程序\n");
    breark;
        default:
           printf( "选择错误\n" );
           break;
       }
    } while (input);
     
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    上面中选择1~4都有好多重复或者很相似的代码,要是把计算机功能加多点的话,就要加很多代码,其中有很多相同重复的代码,我们可以封装成一个函数来实现功能从而避免重复写那么一样的代码;那么这些功能每个本来就是一个函数,该怎样才能整合到一个函数来可以调用所有功能函数呢?

    void computer(int (*cmp)(int x,int y)){
    printf( "输入操作数:" );
           scanf( "%d %d", &x, &y);
           ret = cmp(x, y);
           printf( "ret = %d\n", ret);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我觉得这个函数可以解决了哈,下面switch语句直接调这个函数,把功能函数传过来就行了,有一个要注意的是必须符合返回值,参数都是相同类型的才行,这里的是两个int类型的参数,返回值是int类型,这样的函数才能传过来进行运算!!!这个就算函数指针的一个用途了;

    1.2函数指针数组的用途

    还是上面那个大的代码,用函数指针数组来运用,把那些功能函数用数组来搞,看代码如何实现

    #include <stdio.h>
    int add(int a, int b)
    {
         return a + b;
    }
    int sub(int a, int b)
    {
         return a - b;
    }
    int mul(int a, int b)
    {
         return a*b;
    }
    int div(int a, int b)
    {
         return a / b;
    }
    int main()
    {
    int x, y;
      int input = 1;
      int ret = 0;
      int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
      while (input)
      {
         printf( "*************************\n" );
         printf( " 1:add      2:sub \n" );
         printf( " 3:mul      4:div \n" );
         printf( "*************************\n" );
         printf( "请选择:" );
       scanf( "%d", &input);
         if ((input <= 4 && input >= 1))
        {
         printf( "输入操作数:" );
           scanf( "%d %d", &x, &y);
           ret = (*p[input])(x, y);
        }
         else
           printf( "输入有误\n" );
         printf( "ret = %d\n", ret);
      }
       return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    调用的时候不用那个解引用的 *符号也可以的,直接p [input]) ( x , y );这个就是我们函数指针数组的一个用处,也叫转移表哈;

    二,指向函数指针数组的指针

    这个是指针,然后是把函数指针数组的地址存进来的哈,这个的话就是了解一下就行了,知道如何写,看得懂就行了哈;

    void test(const char* str)
    {
    printf(“%s\n”, str);
    }
    int main()
    {
    //函数指针pfun
    void ( * pfun )( const char * ) = test;
    //函数指针的数组pfunArr
    void ( * pfunArr[5] )( const char * str);
    pfunArr[0] = test;
    //指向函数指针数组pfunArr的指针ppfunArr
    void ( * ( * ppfunArr)[5] ) (const char * ) = &pfunArr;
    return 0;
    }

    三,回调函数

    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个
    函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
    的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进
    行响应。
    就是我们不是直接调用这个函数,而是把函数地址传过来,在另外一个函数里面通过函数指针调用这个函数,这样会不会更容易懂一些?我们qsort库函数就是典型的回调函数;

    #include <stdio.h>
    //qosrt函数的使用者得实现一个比较函数
    int int_cmp(const void * p1, const void * p2)
    {
     return (*( int *)p1 - *(int *) p2);
    }
    int main()
    {
      int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
      int i = 0;
     
      qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
      for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
     {
       printf( "%d ", arr[i]);
     }
      printf("\n");
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    下面要模拟实现qsort库函数,我以前写过一篇模拟实现qsort函数的博客可以看看;
    qsort库函数的模拟实现

    总结

    后面还有一篇长的指针面试题的题目解析博客,然后指针系列博客暂时就告一段落了;
    在这里插入图片描述

  • 相关阅读:
    Windows安装FFmpeg说明
    送你一份价值10W的非专业的面试技巧
    设计模式——抽象工厂模式
    动态RDLC报表(六)
    【博客436】kubeadm init原理
    Spring MVC的执行流程
    MNN简介
    gRPC之grpc resolver
    ElasticSearch - ES集成ik分词器
    全面了解 Redis 高级特性,实现高性能、高可靠的数据存储和处理
  • 原文地址:https://blog.csdn.net/qq_68844357/article/details/125440178