世界是我们的!! 伟人如是说
在前面几篇博客已经将大部分指针的理论知识介绍了(当然只是初阶的),这篇博客将用几个程序来进一步强化我们对指针的了解。
1.qsort函数的认识
在此之中我们可能对于最后一个参数还是不太清楚,我们知道他是一个函数指针类型,但这个参数为什么是const void*呢?我们接下来通过两个程序来回答这个问题
比较整数
比较结构体
通过这两个例子,我们可以知道cmp函数中的参数设置为const void*的原因就是为了使这个函数的接口可以匹配不同类型功能,如果我们给定了类型,那么我们传参时只能传对应类型的变量,那么我们也就只能实现指定的一种功能,而我们这里可以传不同的变量,通过强转实现了不同功能的使用。
我们接下来来改造冒泡排序,让它能够排序任何算法(qsort函数的实现涉及数据结构的内容,较为复杂,不易讲解)
我们先了解了解它的大致过程,冒泡排序的核心便是两两比较,将最大(最小)放到一轮的最后,再进行下一轮的排序,但我们上述交换的内容显然不符合我们的要求,因为变量可能是其它类型,而这里我们使用中间变量是一个特定的类型即整形,这样我们只能完成整形的排序,并且我们比较大小的方法也是不符合的,我们知道>运算符只能比较整形,因此我们要考虑考虑我们上面给定的形参(我们现在才用到sz),接下来我们一步一步解决这些问题(难点)
比较arr[j] 和 arr[j+1]
我们知道cmp的参数是两个函数指针,既然是指针就说明这里我们需要传地址,但我们可能会产生一个疑惑,为什么传地址就可以进行比较呢?
我们拿这个函数(比较整数)来看,这里我们对p1和p2进行强转
我们知道在计算机中,顺序表是连续存储的,在这里我们已经知道顺序表首元素的地址(base),也知道顺序表中存储变量的大小(width),这样我们就可以得到每一个元素(如上图)并且将他们进行比较(这里是返回它们的差值),比较字符串的例子也一样,不过是使用strcmp函数来比较罢了。
交换两个元素
我们在交换时的难点在于不清楚变量的类型,无法直接给定一个特定类型的中间变量,这里我们有一种方法可以越过这一点,直接交换内存单元上的数据,char*类型只会访问一个字节内容,因此在交换变量内容中需要知道宽度,将一个变量中所有内容都交换,当然这里和上面比较时取内存略有差异,我们拿结构体比较的函数来看
上面这里只取了结构结构体的一部分进行比较,而我们交换内存时将整个元素(width大小内存单元)进行了交换(下面这张图具体内存单元未计算)
我们来看看个程序
我们在使用时会发现实现的功能与qsort函数一致(效率有差异)
结语:
至此,我们的指针系列结束了,希望这些博客能有助于你们加深对于指针的理解,当然由于作者也是小白,博客中不可避免会出现一些错误,希望大家能够带着思考去学习并指出这些问题。最后祝愿每一个努力之人都可以实现自己的理想!!