第三十七天学习记录:C语言进阶:指针详解Ⅴ

qsort函数
qsort(s,sz,sizeof(s[0]),cmp_stu_by_name);
第一个参数:待排序数组的首元素地址
第二个参数:待排序数组的元素个数
第三个参数:待排序数组的每个元素的大小-单位是字节
第四个参数:是函数指针,比较两个元素的所用函数的地址-这个函数使用者自己实现函数指针的两个参数是:待比较的两个元素的地址

如下是以模拟qsort函数自创一个以冒泡排序为方法的排序函数。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

//void qsort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2));

int cmp_int(const void* e1, const void*e2)
{
	//比较两个整型值的
	return *(int*)e1 - *(int*)e2;
}

void test1()
{
	int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	int i = 0;
	for (i = 0; i < sz; ++i)
	{
		printf("%d ", arr[i]);
	}
}

int cmp_float(const void* e1, const void*e2)
{
	if (*(float*)e1 == *(float*)e2)
	{
		return 0;
	}
	else if (*(float*)e1> *(float*)e2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

void test2()
{
	float f[] = { 9.0,8.0,7.0,6.0 ,5.0,4.0 };
	int sz = sizeof(f) / sizeof(f[0]);
	qsort(f, sz, sizeof(f[0]), cmp_float);
	int i = 0;
	for (i = 0; i < sz; ++i)
	{
		printf("%f ", f[i]);
	}
}

int cmp_stu_by_age(const void* e1, const void*e2)
{
	return ((struct  Stu*)e1)->age - ((struct  Stu*)e2)->age;
}

int cmp_stu_by_name(const void* e1, const void*e2)
{
	//比较名字就是比较字符串,字符串比较不能直接用><=来比较,应该用
	return strcmp(((struct  Stu*)e1)->name, ((struct  Stu*)e2)->name);
}

void test3()
{
	struct  Stu s[3] = { { "Zhangsan",20 },{ "Lisi",30 },{ "Wangwu",10 } };
	int sz = sizeof(s) / sizeof(s[0]);
	//qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

void Swap(char* buf1, char* buf2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		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 - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			//两个元素的比较
			if (cmp((char*)base+j*width,(char*)base+(j+1)*width) > 0)
			{
				Swap((char*)base + j*width, (char*)base + (j + 1)*width,width);
			}
		}
	}
}

void test4()
{
	int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
}

void test5()
{
	struct  Stu s[3] = { { "Zhangsan",20 },{ "Lisi",30 },{ "Wangwu",10 } };
	int sz = sizeof(s) / sizeof(s[0]);
	bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}

int main()
{
	//test1();
	//printf("\n");
	//test2();
	//printf("\n");
	//test3();
	test4();
	//test5();
	return 0;
}

一维数组面试题:

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int main()
{
	//数组名是首元素的地址
	//1.sizeof(数组名)-数组名表示整个数组
	//2.&数组名-数组名表示整个数组
	//
	//一维数组
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//16   sizeof(数组名)-计算的是数组总大小-单位是字节
	printf("%d\n", sizeof(a + 0));//4/8   数组名这里表示首元素的值,a+0还是首元素地址,地址的大小就是4/8个字节
	printf("%d\n", sizeof(*a));//4   数组名表示首元素地址,*a就是首元素,sizeof(*a)就是4
	printf("%d\n", sizeof(a + 1));//4/8   数组名这里表示首元素的值,a+1是第2个元素的地址,地址的大小就是4/8个字节
	printf("%d\n", sizeof(a[1]));//4   第2个元素的大小
	printf("%d\n", sizeof(&a));//4/8   &a取出的是数组的地址,但是数组的地址那也是地址,地址的大小就是4/8个字节
	printf("%d\n", sizeof(*&a));//16   &a是数组的地址,数组的地址解引用访问的数组,sizeof计算的就是数组的大小,单位是字节
	printf("%d\n", sizeof(&a+1));//4/8   &a是数组的地址,&a+1虽然地址跳过整个数组,但还是地址,所以是4/8个字节
	printf("%d\n", sizeof(&a[0]));//4/8   &a[0]第一个元素的地址
	printf("%d\n", sizeof(&a[0]+1));//4/8   &a[0]+1是第二个元素的地址

	return 0;
}

问:

int a[4];printf("%d\n", sizeof(a));

为什么这个输出是16?指针大小不是只有4吗?
ChatAI答:首先需要指出的是,a 并不是一个指针,而是一个整型数组,所以其大小应该是 4 * sizeof(int),一般情况下,sizeof(int) 的结果为 4 字节,所以 sizeof(a) 的结果应该为 16 字节,这是因为数组中有 4 个元素,每个元素占用 4 个字节。

如果你把 a 声明为指针,例如 int *a;,那么输出的结果应该是 4,因为指针大小通常是与机器的位数相关的,32 位指针占用 4 个字节,64 位指针占用 8 个字节。

问:

int a[] = { 1,2,3,4 }; 
printf("%d\n", sizeof(a+0));

为什么第二个输出是4而不是16?
ChatAI答:
在第二个输出中,a+0其实是对a数组的取地址运算,它相当于&a[0],仍然是一个指向整型的指针,所以其大小仅为 4 个字节,而不是整个数组 a 的大小 16 字节。

需要注意的是,在 sizeof 运算符中,对数组名字取大小运算并不会真正地求出数组所占内存的总大小,而是只会计算数组占用内存的字节数。在a+0中,数组名字 a 被写成了指针形式,因此 sizeof(a+0) 的结果是指针变量的大小,也就是 4 字节。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int main()
{
	//字符数组
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6   sizeof计算的是数组大小,6*1=6个字节
	printf("%d\n", sizeof(arr + 0));//4/8  arr是首元素的地址,arr+0还是首元素的地址,地址大小是4/8字节
	printf("%d\n", sizeof(*arr));//1   arr是首元素地址,*arr就是首元素,首元素是字符大小是一个字节
	printf("%d\n", sizeof(arr[1]));//1  arr是第二个元素
	printf("%d\n", sizeof(&arr));//4/8   &arr虽然是数组的地址,但还是地址,地址的大小是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8   &arr+1是跳过整个数组后的地址,地址大小是4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//4/8   第二个元素的地址

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值