当前位置: 首页 > news >正文

【C语言】深入理解指针(4)

目录

一、回调函数

1.什么是回调函数

2.回调函数举例

3.代码的回调流程

二、冒泡排序使用回调函数模拟实现qsort

1.冒泡排序的缺陷

2.qsort()函数的使用

代码的回调流程

3.模拟实现

char*类型的指针变量的妙用

代码的回调流程

4、补充:数据大小的比较


一、回调函数

1.什么是回调函数

回调函数就是一个通过函数指针调用的函数。

如果把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

2.回调函数举例

每一个case语句中虽然执行计算的逻辑 是区别的,但是输入输出操作是冗余的,

 因为case语句中只有调用函数的逻辑有差异,并且实现具体计算的四个函数类型是一样的,所以我们可以把调用的函数的地址以参数的形式传递过去,使用函数指针接收,函数指针指向什么函数就调用什么函数,这里其实使用的就是回调函数的功能。

没有使用回调函数

使用回调函数

3.代码的回调流程

二、冒泡排序使用回调函数模拟实现qsort

qsort()本身不能确定需要排序何种类型的数据,但是提供了一个需要由使用者自己实现的进行大小比较的函数接口

int (*compar)(const void*, const void*)

void*的指针变量只能得到变量地址,不能得到变量的类型,无从得知一个元素有多大,所以不能进行解引用和运算,但是可以接收任意类型的指针变量,使用void*就是为了能接收任意变量类型,再根据自己需要进行强转

冒泡排序使用回调函数模拟实现qsort()也采用这样的思路,底层使用冒泡排序,具体是什么类型的比较需要使用者自己先写出来一个大小比较函数

1.冒泡排序的缺陷

 冒泡排序:

一种排序算法,但是只能进行一种数据类型的排序(如果使用冒泡排序对字符串和结构体等元素进行排序,不能使用 > < 号)

void Bubble_sort(int* arr, int size)
{int tmp = 0;//总共比较的趟数for (int i = 0; i < size - 1; i++){//下标为0的元素在每一趟中比较的次数for (int j = 0; j < size - 1 - i; j++){if (arr[j] > arr[j + 1]){tmp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = tmp;}}}
}

2.qsort()函数的使用

qsort()是库函数中用于实现任意数据类型排序的函数

  • 函数原型如下
  • 比较函数的实现要求
  • 因为qsort函数的设计者无法提前知道使用者需要进行何种类型的数据比较,所以留出来大小比较的函数由使用者自行设计
  • void*不能解引用,也不能进行+-整数的操作,需要使用者根据需要自行进行类型强转

应用实例:

代码的回调流程

3.模拟实现

char*类型的指针变量的妙用

事先不知道会比较何种数据类型,

所以直接使用刚好只能操作一个字节地址的 char 类型指针
通过 char* 加上 size 可以模拟得到任意类型的指针变量

循环size次的char*++可以访问任意类型变量的每个字节地址

//模仿 qsort 将冒泡排序改成使用回调函数实现任意类型的排序,自行实现(以比较整型为例)
int compar(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}//事先不知道会比较何种数据类型
//直接使用刚好只能操作一个字节地址的 char 类型指针
//通过 char* 加上 size 可以模拟得到任意类型的指针变量
//循环 size 次的 char* ++ 可以访问任意类型变量的每个字节地址
void Swap(char* p1, char* p2, size_t size)
{for (int i = 0; i < size; i++){char tmp = *p1;*p1 = *p2;*p2 = tmp;p1++;p2++;}
}int Bubble_sort(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2))
{//总共比较次数for (int i = 0; i < num - 1; i++){//下标为0的元素在每一趟中比较的次数for (int j = 0; j < num - 1 - i; j++){//因为事先不知道比较的是何种数据类型//又因为 char类型的指针+1正好跳过一个字节//所以统一强转成 char* 指针变量,通过 size 跳过不同的距离,从而准确读取不同的数据if (compar((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[5] = { 5,3,4,1,2 };int num = sizeof(arr) / sizeof(arr[0]);Bubble_sort(arr, num, sizeof(arr[0]), compar);for (int i = 0; i < num; i++){printf("%d ", arr[i]);}return 0;
}

代码的回调流程

4、补充:数据大小的比较

整型和浮点型可以使用><号进行比较

字符串使用库函数strcmp()进行比较,需加上头文件#include <string.h>

结构体的比较实际是某一个成员变量的比较

http://www.xdnf.cn/news/1460719.html

相关文章:

  • 【LeetCode热题100道笔记】旋转图像
  • pycharm解释器使用anaconda建立的虚拟环境里面的python,无需系统里面安装python。
  • MySQL复制技术的发展历程
  • Spring启示录
  • 从传统CNN到残差网络:用PyTorch实现更强大的图像分类模型
  • BenTsao本草-中文医学大模型
  • 【算法--链表】61.旋转链表--通俗讲解
  • 【Day 44】Shell-Git版本控制器
  • 【Python】数据可视化之分类图
  • Day2p2 夏暮客的Python之路
  • 数学建模25c
  • [数据结构] 链表
  • 深度学习之第七课卷积神经网络 (CNN)调整学习率
  • MySQL子查询的分类讲解与实战
  • 从基础到实践:Web核心概念与Nginx入门全解析
  • 前端url参数拼接和提取
  • 嵌入式基础 -- I²C 信号与位层规则
  • Swift 解法详解:LeetCode 371《两整数之和》
  • 漏洞绕过方式
  • 从零到一:人工智能应用技术完全学习指南与未来展望
  • ClickHouse 分片、 Distributed 表、副本机制
  • flowable基础入门
  • 【c/c++】深度DFS
  • MATLAB平台实现人口预测和GDP预测
  • 美国教授提出的布鲁姆法,结合AI直击学术科研痛点,写作与创新效率直接翻倍!
  • 漫谈《数字图像处理》之实时美颜技术
  • Java并行计算详解
  • 解决 Rollup failed to resolve import “vue3-json-viewer/dist/index.css“ from xxx
  • 【Docker】P1 前言:容器化技术发展之路
  • JS本地存储