C语言回调函数解析

各位帅哥靓女们,这里是猪猪大讲堂(今天刚改的),今天我们来讨论一些关于函数的问题,上一章中我们谈论了函数指针的问题,有的人就说这个函数指针有啥用?完全就是多此一举,但是今天我们所说的回调函数就是以函数指针为核心的。

【一】什么是回调函数

回调函数就是一个通过函数指针的调用的函数,如果你将这个函数函数的地址作为参数传给另一个函数,当这个指针被用来调用其所指向的函数的时候,我们就说这个是回调函数,回调函数并不是有这个函数的实现者直接调用,而是在特定的条件或事情的发生的时候由事情的另一方调用的,用对于这件事或条件进行相应。

【二】回调函数的典型

回调函数听起来十分的陌生,但是事实上我们都不知道使用它多少次的了,例如我们使用的qsort这个库函数,函数的最后一个参数就是一个compare函数,我们需要这个函数的地址作为参数传给qsort函数,其使用方式如下:

#include <stdio.h>
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;
 }

这个时候就有人要问了,为啥不会再排序设计好的时候就设置好这个比较函数呢?非要等着我们使用的时候去自己编写,这不是增加我们的使用成本吗?但是同学你要想想,你是不是在更改这个返回值之后这个函数的排序的方式就发生了改变,可以改成递增或者是递减的排序,这样话是不是一个函数就可以实现递增和递减的排序,而且你会发现你编写的函数接受的函数类型是void,而且后面会发生类型转化,将这个类型转化为你所需要的比较的两个数据的类型,这个时候是不是什么类型的数据我们都能通过一个函数进行比较?通过上面的这两步,我们是不是极大的减少了函数的编写成本,而且实现了代码的简洁性。

【三】自己手动实现回调函数的冒泡排序

我写好的代码入下:

#include <stdio.h>
int int_cmp(const void * p1, const void * p2) {
  return (*( int *)p1 - *(int *) p2);
}
void _swap(void *p1, void * p2, int size) {
    int i = 0;
    for (i = 0; i< size; i++)
   {
        char tmp = *((char *)p1 + i);
       *(( char *)p1 + i) = *((char *) p2 + i);
       *(( char *)p2 + i) = tmp;
   }
}
void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{
    int i = 0;
    int j = 0;
    for (i = 0; i< count - 1; i++)
   {
       for (j = 0; j<count-i-1; j++)
       {
            if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)
           {
               _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
           }
       }
   }
}
int main()
{
    int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
    //char *arr[] = {"aaaa","dddd","cccc","bbbb"};
    int i = 0;
    bubble(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; }

很多小伙伴都惊呆了,我改良版的冒泡排序为啥参数不一样?有数组的首地址,数组的大小,有数组的成员的大小,还有一个比较函数?

莫急,让我来为你一一解析,我们先进入冒泡函数内部,进行遍历(冒泡的底层原理还是不变的),但是你可以看出来这个比较的函数是我们自己写出来的,比较函数原理和qsort函数是一样的,这里我就不过多赘述了,如果比较结果为真的话,就会启用这个转化函数了,这个转化函数的参数是什么呢?有需要转化的第一个变量的地址和转化的第二个变量的地址,和一个变量的大小,我们继续进入转化函数的内部看看,你能看到这个交换并不是我们所知道的直接数据是啥类型就交换啥类型,二十全部转化为char类型的指针,一个一个字节的交换,c语言中无论什么类型的数据都是按照字节为基本单位,所以char类型的指针完美的实现了这个问题,转化好了继续下一轮的判断,判断函数也是将这个其他类型的函数转化成char类型的函数,然后跳过一个成员的大小,指向下一个成员的位置,然后你自己编写的时候是需要自己转化的,这样就完美的解决了程序的编写复杂度。

【四】回调函数的原理

其实回调函数原理就是将一个函数的指针传给另一个函数,然后函数调用这个函数指针来实现具体的操作,也因为函数指针的特性,导致一个函数可以编译出多种功能从而使代码更加简洁,同时也显得高大上。

tips:这就是这期猪猪所呈现的所有问题,如果各位帅哥靓女们觉得猪猪说的有问题,还请位于评论区斧正,如果觉得猪猪写的还是蛮不错的话,还请给猪猪一键三连,毕竟猪猪码字不易。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值