C语言——指针进阶(三)

2023-09-15 10:14:44

目录

一.前言摘要

二.排序函数qsort的模拟实现

三.指针和数组笔试题解析


一.前言摘要

讲述关于strlen和sizeof对于各种数组与指针的计算规则与用法。另外还有qsort函数的模拟实现(可以排序任意类型变量)

二.排序函数qsort的模拟实现

目标:用冒泡排序的思想,模拟实现一个排序函数,可以排序任意类型的数据。

我们先来进行两个小测试:

测试一:

冒泡排序已经是老主顾了,只要明白每一次对比(最坏情况)的趟数就可以用双层for循环写出来了。

 测试一结束,结论:只能排序整型数组。

测试二:

当我们往bubble_sort函数输入实参时会发现接受实参的变量类型只能是int,与结构体不匹配。

接下来我们就要对bubble_sort函数重新作出修改了。

上岸先斩意中人,改函需修形参路。我们可以发现两个测试传输的实参都是地址,那我们就选择用万金油的void* 指针(可以接收任何类型的地址)进行接收。

除了知道元素的起始地址和个数,还需要知道一个元素的大小,这样下一个元素存放在哪里才能知道。所以我们又引进了一个新的变量size_t size.

下面对内部排序进行分析:

首先无论是整型排序还是结构体排序它的趟数都是一样的,都需要慢慢去对比。唯一要变的是这一段代码。

应对不同类型的对比,两个元素的比较方法也是不一样的,总不能用>来对比结构体吧。

我们不妨提供一个专门对比两个元素大小的函数,如果前一个元素>0那就让cmp返回一个大于0的数,如果相等就返回0,后一个元素大就返回小于0的数。

那我们如何还函数里调用这个cmp函数呢,我们可以在添加一个形参,这个形参是一个函数指针,存储的是cmp函数的地址(这样就可以指向该地址并调用它了),而这个函数指针指向函数的两个参数e1和e2分别是我们需要对比的两个元素(这里用指针来接收它们),最后该函数指针的返回类型是int(因为要分两个元素的大小情况而返回不同的数值)。

因为我们要作相减运算,所以这里对e1和e2进行强制类型转换后再解引用。

接下来我们要思考如何把arr[j]与arr[j+1]的地址传给cmp函数:

通过图示我们可以知道base是指向首个元素的地址的,那能不能对它进行base+1来指向下一个元素呢?答案是不行,虽然void*是万金油可以接收任意类型的地址,但它也有弊端——就是不能+-整数来改变指针指向。

强制转换成int*的话也不合适,那我们干脆就直接强制转换为char*,当我们需要指向下一个元素的时候又知道元素大小,直接加上就可以跳转指向了。一开始我们是9和8比,后面又该如何实现9和7比呢?

既然本质是相邻元素比较,那我们就和j联系起来,通过j*size来实时实现2相邻元素的对比。

我们对两个元素进行交换也要作出相应的变化,由于是不清楚该元素的类型,所以我们采用的是一个字节对应一个字节的交换。

可以有人会有疑惑,这里为什么不直接创造一个第三变量交换呢?假如创建第三变量,那变量类型我们不清楚是没办法创建的。

我们可以通过临时创造出来的字节(char类型)对两个元素的字节一个一个进行交换

至此,这个通用类型的排序函数就改造完成了。我们先来测试一下整型数组test1。

整体结构图:

接下来我们来测试结构体里面的年龄大小:

再创造一个比较结构体的函数

当我们按照年龄来比后:

如果想要按照名字来比:

那就再创建一个函数,只不过字符串对比需要用到strcmp来比较。

整体结构图:

当我们想要把升序改为降序时,来看看应该更改哪些地方。

三.指针和数组笔试题解析

开胃小菜:

整型:

字符:

到&arr这里需要特殊说明一下,虽然strlen接收类型是用const char* str接收,数组指针char(*)[6]会发生类型转换,但本质上整个数组地址和首个元素地址一开始都是一样的,所以strlen还是会从最开始的首个地址开始相后寻找\0

再来一组:

这里并不是把abcdef存到p里面去,更准确的应该是把a的地址存到p里面,让p能够找到abcdef\0这段字符串。

更多推荐

【23种设计模式】组合模式(八)

前言组合模式,英文名称是:CompositePattern。当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达的意思,那就是“俄罗斯套娃”。“俄罗斯套娃”就是大的瓷器娃娃里面装着一个小的瓷器娃娃,小的瓷器娃娃里面再装着更小的瓷器娃娃,直到最后一个不能再装更小的瓷器娃娃的那个瓷器娃娃为止。在我们的操

黑马JVM总结(十)

(1)直接内存_基本使用下面我们看一下使用了ByteBuffer直接内存,大文件的读写效率是非常的高Java本身并不具备磁盘读写的能力,它需要调用操作系统的函数,需要从java的方法内部调用本地方法操作系统的方法,设计到了cpu的用户状态变为内核态,切换到内核态以后,由cpu的函数去读取磁盘文件的内容,会在操作系统中划

【计算机网络】——数据链路层(应用:局域网、广域网、设备 )

//仅做个人复习和技术交流,图片取自王道考研,侵删一、大纲1、介质访问控制信道划分介质访问控制随机访问介质访问控制2、局域网3、广域网4、数据链路层设备二、局域网1、局域网基本概念和体系结构局域网(LocalAreaNetwork):简称LAN,是指在某一区域内由多台计算机互联成的计算机组,使用广播信道。特点1:覆盖的

【python】我用python写了一个可以批量查询文章质量分的小项目(纯python、flask+html、打包成exe文件)

web效果预览:文章目录一、API分析1.1质量分查询1.2文章url获取二、代码实现2.1Python2.11分步实现2.12一步完成2.13完整代码2.2python+html2.21在本地运行2.22打打包成exe文件2.23部署到服务器一、API分析1.1质量分查询先去质量查询地址:https://www.cs

Python垃圾回收机制详解:引用计数与循环垃圾收集器

文章目录Python垃圾回收机制引用计数机制循环垃圾收集器小结详细讲解及实操1.程序中的垃圾问题2.垃圾的定义3.自动垃圾回收机制4.示例:使用del方法删除垃圾对象5.手动处理垃圾回收6.结束程序7.垃圾回收的自动处理8.结束程序python精品专栏推荐python基础知识(0基础入门)python爬虫知识Pytho

MySQL与ES数据同步的四种方案及实践演示

文章目录一、同步双写优点缺点双写失败风险项目演示二、异步双写(MQ方式)优点缺点项目演示三、基于Datax同步核心组件架构图支持的数据源及操作项目演示四、基于Binlog实时同步实现原理优点缺点项目演示一、同步双写也就是同步调用,这是一种最为简单的方式,在将数据写到mysql时,同时将数据写到ES。优点1.业务逻辑简单

14:00面试,14:06就出来了,问的问题有点变态。。。

从小厂出来,没想到在另一家公司又寄了。到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到5月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%,这下搞的饭都吃不起了。还在有个朋友内推我去了一家互联网公司,兴冲冲见面试官,没想到一道题把我给问死了:如果模块请求http改为了h

每日练习-7

目录一、选择题二、算法题1、两种排序方法2、求最小公倍数一、选择题1、解析:指针和引用是C++中两种不同的变量类型,它们都可以用来访问或修改其他变量的值,但是它们有以下几个区别:引用必须在定义时初始化,而指针可以在任何时候初始化。例如,int&r=a;是合法的,但是int&r;是不合法的。而int*p;和int*p=&

02_elasticsearch 核心概念

02_elasticsearch核心概念1、lucene和elasticsearch的前世今生2、elasticsearch的核心概念1、lucene和elasticsearch的前世今生1、lucene和elasticsearch的前世今生lucene:最先进、功能最强大的搜索库。但是直接基于lucene开发,非常复

【Vue】模板语法,插值、指令、过滤器、计算属性及监听属性(内含面试题及毕设等实用案例)上篇

一、引言1、什么是模板语法?Vue的模板语法是一种用于在HTML中声明式地渲染Vue组件的语法。它基于HTML,并通过特定的模板语法扩展了HTML。Vue使用了一种称为“Mustache”语法的模板插值来绑定数据到HTML元素上。在Vue的模板语法中,你可以使用双大括号({{}})将数据绑定到HTML元素上,这样数据的

隔山打牛:金融大崩溃

当2004-2006年美联储主席格林斯潘在任期的末尾一鼓作气把联邦利率从1%拉高到5%,然后把美联储主席的位子交给继任者伯南克的时候,没有人意识到接下来将要发生何等巨变。图:美国联邦利率伯南克把利率稳定在5.3%附近的高位一年左右时间,直到2007年年中。美股从2003年底开始的牛市,一直狂飙到2007年底。标普500

热文推荐