当你能复刻C语言库函数qsort(),你就掌握了用指针玩弄内存:)

本文详细介绍了C语言标准库函数qsort()的使用方法,包括基本概念、函数定义、compar函数的编写以及如何复刻qsort实现排序。特别强调了通过指针操作不同类型数据的技巧和内存访问的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.快速上手qsort()函数

1.1基本信息

  • qsort()函数是stdlib.h中的库函数,通过“快速排序”算法实现对数组的排序。

    1.2 函数定义

    void qsort(void *base,size_t nmemb,size_t size,
              int (*compar)(const void *,const void *));
    
    • base

      传入需要排序的数组的首地址

    • nmemb
      传入需要排序的数组的元素

    • size
      待排序数组中一个元素所占据的内存大小

    • compar
      一个自定义的函数,将决定升序排列还是降序排列。这也是实现对不同类型数据排序的关键。【函数定义中是传入一个函数指针,不熟悉的朋友可以查查相关文章:指针的进阶使用】

    1.3 compar(const void*,const void*)

    ​ 根据qsort()的函数定义,我们需要按需完成compar函数的定义。该函数要求传入两个数据的地址,将他们比较后返回一个整型值。由于函数的参数是两个void类型的指针,我们需要强制类型转换为整型类型的指针,解引用后再将两个值作差,便能比较出两个数据的大小。

    ​ 这样的自定义函数可以给用户很大的操作空间:

    • 相当于将所有数据都转化整型进行操作,实现了对不同数据的排序

    • 排序字符串时,还可以使用string.h中的strcmp()函数直接比较两个字符串,因为其返回值也是整型值

    1.4 样例

#include<stdio.h>


//自定义比较两个int类型数据的compar函数
//实现升序排列
int comp_int(const void* a, const void* b){
	return *(int*)a-*(int*)b;
}

int main(){
	int array1[5] = { 9,8,7,6,5 };
	int size1 = sizeof(array1) / sizeof(array1[0]);

	qsort(array1,size1,sizeof(array1[0]),camp_int);

	int i;
	for(i=0;i<5;i++)
		printf("%d ", array1[i]);
	
	return 0;s

}

2.复刻qsort()函数

2.1实现原理

c语言中的指针,通过地址访问,间接对数据进行操作。不同类型的指针,本质上是在遍历内存时跳过的字节数不同。

例如,32位、64位编译器中,int类型的数据占4字节;float类型的数据占4字节;char类型的数据占1字节。对应的指针在遍历内存时,没加1,跳过的字节数分别是:4字节,4字节,1字节。

内存演示

为了统一对不同类型值的访问,我们可以使用char类型的指针,模仿其他类型的值的指针对数据的访问。这也是为什么需要向qsort函数传入nmeber size两个参数的原因,nmeber相当于划定了指针操作的最大范围,size则规定了指针操作的步长。因此,无论什么类型的数据,只要存储在内存中,我们都可以使用相同方法取得其值,然后对它们进行排序,从而实现包括结构体在内的复杂数据类型的排序。

2.2代码

2.2.1 整型指针实现冒泡排序
void BubbleSort(int* num,int size)
{
    int i,j;
    for(i=0;i<size-1;i++){
        for(j=0;j<size-1-i;j++){
            if(num[j]>num[j+1]){
                int temp=num[j];
                num[j]=num[j+1];
                num[j+1]=temp;
            }
        }
    }
}
2.2.2 复刻qsort()函数
void BubbleSort_Plus(void* base, int num, int size_unit, int(*cap)(const void*, const void*))
{
	int i, j;
	for (i = 0; i < num - 1; i++) {
		for (j = 0; j < num-1-i; j++) {
			if (cap((char*)base+j*size_unit,(char*) base+(j+1)*size_unit)>0) {
				change((char*)base + j * size_unit,(char*)base + (j + 1) * size_unit, size_unit);
			}
		}
	}
}

void change(void* a, void* b, int size_unit)
{
	int i;
	for (i = 0; i < size_unit; i++) {
		char temp = *((char*)a+i);
		*((char*)a + i) = *((char*)b + i);
		*((char*)b + i) = temp;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值