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

news2024/9/23 23:57:40

文章目录

  • 前言
  • 一、回调函数是什么?
  • 二、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.coloradmin.cn/o/2126572.html

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

相关文章

代码随想录27期|Python|Day52|​动态规划|​647. 回文子串|516. 最长回文子序列

本文是动态规划的回文字符串部分。 647. 回文子串 本题需要搞清楚dp的定义、遍历顺序和递推公式。 1、dp数组的定义 由图片可知,不同于之前的dp数组直接定义为当前遍历到的位置处题目所要求得值,而是应该定义为i为开始,j为结束的子串是否是…

探索音视频SDK的双重核心:客户端与服务端的协同作用

在当今的数字化时代,音视频技术已成为连接人与人、人与世界的重要桥梁。从社交娱乐到在线教育,从远程医疗到视频会议,音视频技术的应用无处不在,极大地丰富了我们的生活方式和工作模式。本文将深入探讨音视频SDK的两大核心类别——…

横版闯关手游【全明星时空阿拉德】Linux手工服务端+运营后台+双app端

横版闯关手游【时空阿拉德】(【全明星阿拉德】)阿拉德系列2022整理Linux手工服务端余额充值后台安卓苹果双端。 运营后台看目录结构是thinkphp开发的。 代码免费下载:百度网盘

DNAT和SNAT实践

NAT分SNAT和DNAT两种。从名字上区分: SNAT将源IP地址替换为出口网络的IP地址,以便内网地址可以访问外网服务。一般受限于公网IP有限,一个内网集合想访问外网服务,则用统一的出口做代理。出口配置公网IP,帮助从此发出的…

Java重修笔记 第五十四天 坦克大战(二)常用的绘图方法、画出坦克图形

常用的绘图方法 1.设置当前画笔的颜色,可多次调用 public abstract void setColor(Color c) 参数:c -颜色 2. 画一条直线 public abstract void drawLine(int x1, int y1, int x2, int y2) 参数:x1 - 第一个点的 x坐标。 y1 - 第一点的 y坐…

Git使用—把当前仓库的一个分支push到另一个仓库的指定分支、基于当前仓库创建另一个仓库的分支并推送到对应仓库(mit6828)

目录 背景提示 将当前仓库的一个分支push到另一个仓库的指定分支 直接基于仓库rep1中的某个分支创建新的分支并将其推送到目标仓库rep2 补充 参考链接 背景提示 最近打算做一下mit6.828的项目,这个仓库使用问题困扰了自己一段时间,由于6828官方提供…

92、K8s之ingress下集

一、ingress 1.1、两种部署方式 1、ingress------------deployment nodeport ​ daemonset hostnetwork----每台设备只能有一个pod,因为直接使用宿主机的端口,所以只能开启一个pod。 2、ingress------svc------deployment里面的pod,这种…

文件IO编程

文章目录 文件描述符相关系统调用文件有关的系统调用文件操作函数--creat函数文件操作函数--open函数文件操作函数--read函数文件操作函数--write函数文件操作函数--close函数文件操作函数--lseek函数缓冲区的大小对性能的影响 实验:调用系统函数,实现文…

Linux:体系结构和操作系统管理

目录 一、冯诺依曼体系结构 1.问题1 2.问题2 二、操作系统管理 一、冯诺依曼体系结构 本章将会谈论一下对冯诺依曼计算机体系结构的理解。 在2024年,几乎所有的计算机,都遵守冯诺依曼体系结构。 冯诺依曼体系结构是应用在硬件层面的,而硬…

Docker高级管理--Compose容器编排与私有仓库(Docker技术集群与应用)

本文介绍了Docker的三大工具:Docker Machine用于创建和管理Docker主机,Docker Compose用于单引擎模式下的多容器应用部署和管理,而Docker Swarm则是一个集群管理工具,提供微服务应用编排功能。Docker Machine支持在不同环境配置Do…

【代码随想录训练营第42期 Day56打卡 - 图论Part6 - 并查集2 - 冗余连接问题

目录 一、做题心得 二、题目与题解 题目一:108. 冗余连接 题目链接 题解:并查集 题目二:109. 冗余连接II 题目链接 题解:并查集 三、小结 一、做题心得 冗杂连接问题是图论章节应用并查集的经典问题。所有的顶点通过边相…

Redis 篇- 实战项目中使用 Redis 实现经典功能(异步秒杀商品、点赞功能、共同关注的好友、投喂功能)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 使用 Redis 实现异步秒杀 1.1 基于 Lua 脚本判断是否符合条件:库存是否充足、一人一单 1.2 基于 Redis 中的 Stream 实现消息队列 1.3 使用 Java 操作…

Unity Hub自动安装指定版本Unity的Android开发环境

Unity开发Android环境要求SDK、DNK、JDK、Gradle版本都要对才能发布APK,自己去配置很容易出错。Unity Hub可以自动安装指定版本Unity的Android开发环境。 1.安装国内用的UnityHub(我这里用的3.3.2-c6) 2.找到对应的Unity版本 3.点击【从Unit…

docker管理redis集群

1.拉取redis镜像 docker pull redis拉取完成 [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE redis latest a617c1c92774 3 years ago 105MB2.运行redis容器 docker run -itd --name redis-test01 -p 6379:6379…

谈谈PCIe VID、DID、SSID、SSVID背后的智慧

PCIe Vendor ID 想了半天还是觉得从“ID是什么”这个问题开始比较好。那么ID是什么?ID就是身份。那身份又是什么?身份就是一个合理存在,用于区分不同个体。为什么叫“合理存在”呢?如果国家不给你发身份证,你就是黑户…

记一次导入dbf文件后数据为空问题的解决方法

前言 省流:这篇文章最终采用的是更换导出文件格式的方法,看到这里觉得方法不适用的小伙伴可以不用浪费几秒钟看完这篇文章哦。 问题描述 作者使用的是Navicat数据库管理工具,然后在将源数据库的数据表导出为dbf格式文件后,再将…

F110批量付款如何Debug BTE增强(后台JOB的调试方法)

F110批量付款如何Debug BTE增强(后台JOB的调试方法) SAP系统中的F110(Automatic Payment)是一个常用的付款程序,在实施过程中,也经常会遇到一些运行的错误,而对于此类的错误,通常的…

基于SpringBoot的租房网站系统

你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言:Java 数据库:MySQL 技术:SpringBoot框架 工具:ECLIPSE 系统展示 首页 管理员功能界面 用户信息界面 预约看房界…

动手学深度学习(pytorch)学习记录28-使用块的网络(VGG)[学习记录]

目录 VGG块VGG网络训练模型 VGG块 定义了一个名为vgg_block的函数来实现一个VGG块 import torch from torch import nn from d2l import torch as d2ldef vgg_block(num_convs, in_channels, out_channels):layers []for _ in range(num_convs):layers.append(nn.Conv2d(in_…

线程池原理及改造

目录 一 线程池执行原理 二 线程池改造(一) 三 线程池改造(二) 一 线程池执行原理 首先我们先了解一下线程池里面几个参数: 第一个是核心线程数,第二个是线程池最大线程数。(线程池里面的线程分为核心线程和非核心线程,既然核心…