C语言 指针进阶7 8最终篇 模仿qsort函数实现冒泡排序通用算法 指针题

模仿qsort函数实现冒泡排序通用算法

bubble_sort

void Swap(char* buf1, char* buf2, int width)
{

	int i = 0;
	for (i = 0; i < width; i++)
	{
		//*buf 访问一个字节
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}



void bubble_sort(void* base,
	int sz,
	int width,
	int(*cmp)(const void* e1, const void* e2))

{
	int i = 0;//确定趟数
	for (i = 0; i < sz; i++)
	{
		int j = 0;//一趟的元素
		for (j = 0; j < sz - 1 - i; j++)
		{
			//两个元素比较
			//假设整型数组比较 arr[j] arr[j+1]
			//e1 e2是指向下面两个元素的指针所以要用地址。


			if (cmp((char*)base + j * width, (char*)base+(j+1)*width) > 0)
			{
				//为什么是(char*)base
				//char* 是1byte正好是最小的,可以用来随意改变访问的跨度
				//因为char* 所占内存最小,加一个元素所占字节就一定会跳到下一个元素的地址。若是转化为int* 等其他类型,而元素所占字节小于4,加上元素所占字节,就不能跳到下一个元素。
				//(char*)base+几个字节就是偏移几个字节



				//交换  .只给起始地址不够因为不知道交换的类型 所以加上了width
				Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);//传两个地址加一个字节个数 ,单个字节进行交换
				//因为元素的类型肯定是相同的,即使我们不知道具体的元素类型是什么,具体有几个字节。但是我们通过char指针,将两个元素的每个字节都进行交换,这样也可以达到交换的效果

			}
		}
	}
}

int cmp_int(const void* e1, const void* e2)
{


	return *(int*)e1 - *(int*)e2;
}
void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d", arr[i]);
	}
	printf("\n");

}

void test1()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);//10个数排序需要9躺 所以需要提前计算元素个数


	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print_arr(arr, sz);


	return 0;
}


	struct Stu
	{
		char name[20];
		int age;

	};
	int sort_by_age(const void* e1, const void* e2)
	{
		return   ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
	}
	int sort_by_name(const void* e1, const void* e2)
	{
		return   strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);

	}//名字是字符串所以用strcmp  他的返回值是一样的.strcmp是比较字符串大小的函数 两个参数之间用,隔开 返回值只有正副和0
	void test2()
	{
		struct Stu s[] = { {"zhangsan",30},{"lisi",34},{"wangwu",20} };
		//年龄排序
		int sz = sizeof(s) / sizeof(s[0]);
		//qsort(s, sz, sizeof(s[0]), sort_by_age);
		bubble_sort(s, sz, sizeof(s[0]), sort_by_name);


	}
	



int main()
{
	//模仿qsort函数实现冒泡排序通用算法
	test1();
	test2();
 return 0;
}

在这里插入图片描述

没有具体类型所以能存储任意类型的指针,但是不能解引用

数组名

//sizeof(数组名) 数组明表示整个数组的 计算的整个数组的大小
//&数组名 数组名表示数组  取出的是整个数组的地址
//除此之外 所有的数组名都是数组首元素的地址
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16
	printf("%d\n", sizeof(a+0));//第一个元素地址   4/8因为32平台4
	printf("%d\n", sizeof(*a));//4  *a是第一个元素   计算第一个元素个数..  地址解引用得到元素
	printf("%d\n", sizeof(a+1));//4/8  第2个元素地址   计算地址的大小
	printf("%d\n", sizeof(a[1]));//4  计算第二个元素大小


	printf("%d\n", sizeof(&a));//4/8  虽然是数组的地址 但也是地址 sizeof(&a)计算的一个地址的大小
	printf("%d\n", sizeof(*&a));//16     计算数组的大小
	//&a --int (*p)[4]=&a;    *&相当于可以抵消
	printf("%d\n", sizeof(&a+1));//4/8   整个数组后的地址
	printf("%d\n", sizeof(&a[0]));//4/8   拆分先看a【0】
	printf("%d\n", sizeof(&a[0]+1));//4/8 加一第二个地址  


	return 0;





}

在这里插入图片描述
**&a取出整个数组地址 +1就是跳过这个数组的地址 **

字符数组

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	//printf("%d\n", sizeof(arr));//6
	//printf("%d\n", sizeof(arr + 0));//4/8  地址大小
	//printf("%d\n", sizeof(*arr));//1   找到a  sizeof(a)就是一个字节
	//printf("%d\n", sizeof(arr[1]));//1
	//printf("%d\n", sizeof(&arr));//4/8
	//printf("%d\n", sizeof(&arr+1));//4/8
	//printf("%d\n", sizeof(&arr[0] + 1));// 4/8


	printf("%d\n", strlen(arr));//随机值  内存空间很大不知道什么时候遇到\0
	printf("%d\n", strlen(arr + 0));//随机值
	printf("%d\n", strlen(*arr));//报错  a    a的ascii值是97   strlen看待指针变量就是地址
	printf("%d\n", strlen(arr[1]));//报错
	printf("%d\n", strlen(&arr));//随机值 &arr去除是数组地址 只要穿过去就变成字符地址
	printf("%d\n", strlen(&arr + 1));//随机值 (-6)
	printf("%d\n", strlen(&arr[0] + 1));//随机值 (-1)

	return 0;

}

int main()
{
	//char arr[] = "abcdef";
	[a b c d e f \0]
	//printf("%d\n", sizeof(arr));//7
	//printf("%d\n", sizeof(arr + 0));//4/8
	//printf("%d\n", sizeof(*arr));//1
	//printf("%d\n", sizeof(arr[1]));//1
	//printf("%d\n", sizeof(&arr));//4/8
	//printf("%d\n", sizeof(&arr + 1));//  4/8
	//printf("%d\n", sizeof(&arr[0] + 1));// 4/8




	char arr[] = "abcdef";

	    printf("%d\n", strlen(arr));//6
		printf("%d\n", strlen(arr + 0));//6
		printf("%d\n", strlen(*arr));//err
		printf("%d\n", strlen(arr[1]));//err

		printf("%d\n", strlen(&arr));//6
		printf("%d\n", strlen(&arr + 1));//随机值
		printf("%d\n", strlen(&arr[0] + 1)); //5
	
}

int main()
{
	//char *p = "abcdef";
	[a b c d e f \0]
	//printf("%d\n", sizeof(p));//4/8
	//printf("%d\n", sizeof(p + 1));//4/8
	//printf("%d\n", sizeof(*p));//1
	//printf("%d\n", sizeof(p[0]));//1   p[0]->*(p+0)
	//printf("%d\n", sizeof(&p));//4/8    取地址p的地址也是地址
	//printf("%d\n", sizeof(&p + 1));//4/8    因为&的是p的地址 所以还在p单独分配的那块空间内 
	//printf("%d\n", sizeof(&p[0] + 1));// 4/8


	char* p = "abcdef";
	//[a b c d e f \0]
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	printf("%d\n", strlen(*p));//err    a
	printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));// 随机值 
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));// 5

}

在这里插入图片描述
图解 p里存放a的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值