C语言深入理解指针五(18)

文章目录

  • 前言
  • 一、回调函数是什么?
  • 二、qsort使用举例
    • 使用qsort函数排序整型数据
    • 使用qsort函数排序结构数据
  • 三、qsort的模拟实现
  • 总结


前言

  本篇将会很有意思!


一、回调函数是什么?

  回调函数就是一个通过函数指针调用的函数。
  如果你把函数的指针(地址)作为参数传给一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另一方调用。

二、qsort使用举例

使用qsort函数排序整型数据

qsort函数能够实现任意类型数据的排列

请看qsort的函数原型
void qsort (void* base, // base指向了要排序的数组的第一个元素
size_t num, // base指向的数组中的元素个数(待排序的数组的元素的个数)
size_t size, // base指向的数组中元素的大小 (单位是字节)
int (* compar)(const void*,const void*)); // 函数指针-指针指向的函数是用来比较数组中的2个元素的
我们发现,假如排序的时候,复杂对象是无法直接用大于号还是小于号的,但是我们可以定制比较方式compar

我们来个具体例子,假设一个比较方式cmp_int
int cmp_int(const void* p1, const void* p2)
{
  return *(int *)p1 - *(int *)p2;
}

使用qsort函数排序结构数据

我们来测试qsort函数排序结构体数据
结构体类型如下:
在这里插入图片描述
按照年龄来比较,我们有以下语句:
在这里插入图片描述
比较函数如下:
在这里插入图片描述

可能有人会问,怎么依靠比较函数的返回值大于小于或者等于就排序了呢,答案是,交换的时候,加个判断条件(后续我们会来个以冒泡排序为核心的例子):
在这里插入图片描述

三、qsort的模拟实现

先看正常情况下,int型数组的比较大小:
在这里插入图片描述
我们发现,这种存在一些问题,需要改造:
1.元素的比较需要修改,有些类型比如说结构体无法用大于小于号来比较
2.交换的代码需要改变 (这个逻辑很巧妙,你往下看)
3.参数也得重新设计,这样只能接受整型数组,应该改为能接收任何数组

请注意,函数原型是BubbleSort(void* base, size_t sz, size_t width, int (*cmp)(const void *p1, const void *p2));

所以说,原先在arr[j] > arr[j + 1]条件下进行交换,现在也就可以看成cmp()>0情况下进行交换
至于cmp里面的数,我们现在来想以下base中下标为j的地址怎么求?显然是base的地址加上j个width个字节,这里需要把base给强制转换成char* 类型的指针,所以cmp函数的p1,p2参数接收的是:
p1:(char*)base + j * width ;p2: (char*)base + (j + 1) * width;

接下来我们思考怎么交换 -> swap(char* buf1, char* buf2, int width):
往下看之前,你不妨思考一下为什么是char*
原来交换的时候,创建一个int临时变量,可是关键是我们现在并不知道要交换元素的类型
可是我们知道两个元素的地址和这个要交换元素类型的长度(字节数)!
这时候!!!我们可以交换width个字节,这样整体来看就是交换了两个元素!!!
如下:
在这里插入图片描述

在这里插入图片描述

至此,参数的重新设计、比较大小,交换三个难点都已经解决了!

总结

  这篇文章应该会让你对指针有个别样的认识
  指针太重要了,下一篇我会以练习题为主来巩固

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/879174.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++——STL——栈(stack)

栈的定义 栈 ( stack )是限定仅在表的一端进行插入和删除操作的线性表,允许插入和删除的一端称 为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。 栈的示意图 因为栈只能够在一端进行插入和删除,所以…

大数据之Flink(三)

9.3、转换算子 9.3.1、基本转换算子 9.3.1.1、映射map 一一映射 package transform;import bean.WaterSensor; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; impor…

鸿蒙交互事件开发04——手势事件

1 概 述 手势事件是移动应用开发中最常见的事件之一,鸿蒙提供了一些方法来绑定手势事件。通过给各个组件绑定不同的手势事件,并设计事件的响应方式,当手势识别成功时,ArkUI框架将通过事件回调通知组件手势识别的结果。 …

王道考研操作系统笔记(一)

虚拟内存的定义和特征: 基于局部性的原理, 在程序装入时,可以将程序中很快用到的部分装入内存,暂时用不到的数据装入外存,就可以让程序开始执行,在程序执行过程中,当所访问的信息不在内存的时…

frida主动调用init_array中的函数

ida打开目标so,查看要主动调用的函数 前提是先过掉检测frida等等,然后控制台启动 输出so地址 Process.findModuleByName("libmod.so") New函数 var aa new NativeFunction(ptr(0x785e002000).add(0x134EC0),"void",[]) 主动调用 a…

如何让人工智能训练更快

影响人工智能训练时间的因素 在深度学习训练中,训练时间的计算涉及到多个因素,包括 epoch 数、全局 batch size、微 batch size、计算设备数量等。下面是一个基本的公式来说明这些参数之间的关系(注意,这只是一个基本的说明公式&…

Makefile文件理解

https://zhuanlan.zhihu.com/p/629855009 参考链接 这个链接我没都看,等用的时候再看吧 我遇到的文件是下面这张图片,然后23行两条命令和在命令行中执行是一样的。

E32.【C语言 】练习:蓝桥杯题 懒羊羊字符串

1.题目 【问题描述】 “懒羊羊”字符串是一种特定类型的字符串,它由三个字符组成,具有以下特点: 1.字符串长度为 3. 2.包含两种不同的字母。 3.第二个字符和第三个字符相同 换句话说,“懒羊羊”字符串的形式应为 ABB,其中A和B是不…

k8s 资源管理

文章目录 ResourceQuota什么是资源配额定义一个ResourceQuotaResourceQuota的使用 LimitRangeLimitRange的用途示例1:配置默认的requests和limits 节点故障大部分都是由于资源分配不合理、超额分配引起的,因此需要用某个技术手段保证节点的资源不会过大地…

【HCIA-Datacom】网络参考模型

网络参考模型 1. 应用和数据2. 网络参考模型与标准协议OSI参考模型TCP/IP参考模型与标准协议常见的几种协议应用层传输层网络层和数据链路层物理层 3. 数据通信过程思考题测一测 ⭐在上一章节中已经给大家介绍了我们网络与生活之间的一些联系 ⭐这一章节主要学习的内容叫做网络…

GDB 查看汇编

查看汇编 x disassemble

C++从入门到起飞之——string类用法 全方位剖析!

🌈个人主页:秋风起,再归来~🔥系列专栏:C从入门到起飞 🔖克心守己,律己则安 目录 1. 为什么学习string类? 1.1 C语言中的字符串 1.2 两个面试题(先不做讲解) 2. 标准库中…

Vulnhub-RickdiculouslyEasy靶机攻略

御剑扫描到ip 一.第一个flag 主机扫描 目录扫描 二.网页信息收集-第二个flag 9090也开放了web服务所以我们在IP地址后面加端口试试,如下图,加上了端口,并且发现了第二个flag,也对第二个flag进行了简单的探索也没有发现什么可以…

内存卡提示格式化怎么办?轻松应对格式化

在日常使用电子设备时,我们有时会遇到内存卡提示需要格式化的情况。这种情况往往让人感到焦虑和困惑,因为格式化意味着内存卡上的所有数据都将被清除。然而,在遇到这种情况时,我们不必过于惊慌。本文将介绍四种方法,帮…

如何获取MySQL数据表的列信息

在数据库管理中,了解表的结构是至关重要的。在MySQL中,我们可以通过几种方式来获取数据表的列信息。这不仅可以帮助我们更好地理解表的结构,还可以在编写查询时提供便利。以下是三种常用的方法来获取MySQL数据表的列信息。 使用 SHOW COLUMN…

UDP通信实现

目录 前言 一、基础知识 1、跨主机传输 1、字节序 2、主机字节序和网络字节序 3、IP转换 2、套接字 3、什么是UDP通信 二、如何实现UDP通信 1、socket():创建套接字 2、bind():绑定套接字 3、sendto():发送指定套接字文件数据 4、recvfrom():接收指定地址信息的数据 三…

如何逆转Instagram账号流量减少?4个实用技巧分享

Instagram作为全球十大社媒之一,不仅是个人分享生活的平台,还是跨境卖家进行宣传推广和客户开发的关键工具。在运营Instagram的过程中,稍有不慎就容易出现账号被限流的情况,对于账号状态和运营工作的进行都十分不利。 一、如何判断…

怎么调整图片亮度?关于调整图片亮度的几种方法推荐

怎么调整图片亮度?调整图片亮度是图像编辑中的一项基本但至关重要的操作。亮度直接影响图像的视觉效果和清晰度,它能够改变照片的整体氛围和表现力。无论你是在处理个人拍摄的照片、编辑设计作品,还是进行专业的图像修复,适当的亮…

API安全 | 发现API的5个小tips

在安全测试目标时,最有趣的测试部分是它的 API。API 是动态的,它们比应用程序的其他部分更新得更频繁,并且负责许多后端繁重的工作。在现代应用程序中,我们通常会看到 REST API,但也会看到其他形式,例如 Gr…

adb有线连接正常,adb connect失败

adb connect失败 1. 确认两个设备在同一个局域网 2. 确认此网络是否有adb连接的权限(有的公司网络不允许adb) 3. 确认防火墙设置 如果前面3步都确认没问题,Ping ip也能成功,那么有可能就是端口的问题: step1: 先用有线连接设备&#xff0…