【C语言进阶】回调函数

【C语言进阶】回调函数


八、回调函数

1 介绍

回调函数就是一个通过函数指针调用的函数。(函数指针实现回调函数)

如果把函数的地址作为参数传递给另一个函数,当这个函数指针被用来调用其所指向的函数时,就说这是回调函数。

回调函数不是由该函数的实现方法直接调用,而是在特定的的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行相应。

示例:

A  <------>  B(*pfA)    
//将A函数的地址传递给B函数,在B函数内部通过函数指针调用A函数,那么B函数就被称为回调函数。


2 qsort() 函数

qsort() 是C语言的一个标准库函数,定义在 <stdlib.h> 头文件中。

qsort() 函数用于对数组进行快速排序,它是一个通用的排序函数,支持对不同类型的元素进行排序

2.1 函数原型

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


2.2 功能

  • 对长度为 num 的数组的元素进行排序,每个元素的字节长度为 size

  • 此函数使用的排序算法通过调用指定的函数 compar 来比较元素对,并将指向它们(元素)的指针作为参数。

  • 该函数不返回任何值,而是通过重新排序其元素来修改指向的数组的内容。


2.3 函数参数

base

  指向要排序的数组的第一个元素的地址

num

  指向的数组中的元素个数。是无符号整数类型(size_t <–> unsigned)。

size

  数组中每个元素的大小(以字节为单位)。是无符号整数类型(size_t <–> unsigned)。

compar

  指向函数的指针,用于自定义排序规则。指针指向比较两个元素的函数。函数原型:

int compar (const void* p1, const void* p2);

  compar() 函数通过返回值来确定当前比较的两个数据的顺序,如下表所示。

返回值意义
<0p1 指向的元素位于 p2 指向的元素之前
0p1 指向的元素等同于 p2 指向的元素
>0p1 指向的元素在 p2 指向的元素之后

2.4 返回值

无,qsort() 函数没有返回值,函数执行完成后,base 数组中存储的就是有序序列。


2.5 qsort() 函数的使用

代码示例

#include<stdio.h>

#include<stdlib.h>
//qsort函数在使用前必须先实现一个比较函数
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);//先强制类型转换,然后再进行解引用,最后相减比大小
}
int main()
{
	int arr[10] = { 1,3,5,7,9,2,4,6,8,10 };

	qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);//回调函数

	int i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);//1 2 3 4 5 6 7 8 9 10 
	}
	printf("\n");

	return 0;
}

解释说明

1 qsort() 是C语言的一个标准库函数,定义在 <stdlib.h> 头文件中。

2 void* 类型的指针,不能直接进行解引用或者进行指针运算;但是却可以接收任意类型的地址


3 模拟 qsort() 函数实现冒泡排序

使用回调函数,模拟实现 qsort 函数,采用冒泡排序的方式。

代码示例

#include<stdio.h>

//自定义比较函数
int int_cmp(const void* p1, const void* p2)
{
	//返回两数之差
	return *((int*)p1) - *((int*)p2);//void*指针不能直接解引用
}
//字节大小为size的两个元素进行交换的函数
void my_swap(char* p1, char* p2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)//每次交换一个数
	{
		//一个字节一个字节进行交换,大小端存储不影响
		char temp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = temp;
	}
}
//qsort()函数以冒泡排序的方式实现
void my_bubble(void* base, size_t num, size_t size, int(*cmp)(const void*, const void*))
{
	int i = 0;
	for (i = 0; i < num - 1; i++)//排序躺数
	{
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)//每趟排序对数
		{
			//交换成升序序列
			if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				//如果 下标为j的元素 > 下标为j+1的元素,就发生交换
				my_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}
int main()
{
	//模拟实现qsort()函数,采用冒泡排序的方式

	int arr[10] = { 1,3,5,7,9,2,4,6,8,10 };

	my_bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);

	//打印排序后的数组元素
	int i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}

解释说明

1 (char*)base + j * size

  basevoid 类型的指针,不能直接解引用或直接进行指针运算,所以必须先强制类型转换为 char 类型的指针;类型决定指针解引用访问多少字节的空间一个 char 类型的指针进行解引用能访问内存中一个内存单元

  j * size 表示(char*)base 的基础上,跳过 j 个字节的空间(+ 表示向后)

2 函数原型说明:

//比较两个数的大小,返回的是两个数的差值
int int_cmp(const void* p1, const void* p2);

//交换字节大小为size的两个数,一次交换一个字节大小()函数以
void my_swap(void* p1, void* p2, int size);

//模拟qsort()函数以bubble冒泡排序的形式实现
void my_bubble(void* base, int count, int size, int(*cmp)(void*, void*));
//			      数组名      数组长度    元素类型   比较函数的地址(函数指针实现回调函数)

3 交换函数

  逐字节交换任意类型的两个数,一次交换一个内存空间的内容。

  比如:int 类型占4个内存空间,那就交换4次。

逐字节交换两个int类型的数


总结:

  本节介绍了什么是回调函数;给出了 qsort() 函数的使用;最后通过模拟 qsort() 函数实现了冒泡排序。


感谢您的阅读!如有任何错误,欢迎您的批评指正!

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言进阶高级编程PDF》是一本以C语言为主题的进阶级别编程书籍,旨在帮助读者提升C语言编程水平并掌握更高级的编程技巧和思维方式。 该PDF书籍的内容包括但不限于以下几个方面: 1. 数据结构与算法:介绍了常用数据结构(如链表、栈、队列、树等)的实现原理和使用方法,以及一些常见算法(如排序、查找等)的实现。 2. 指针与内存管理:探讨了指针的概念、指针和数组、指针和函数等相关内容,以及如何进行动态内存管理和资源释放。 3. 文件操作:介绍了C语言中对文件的读写操作方法,包括文件的打开、写入、读取和关闭等。 4. 高级函数和宏:介绍了C语言中的函数指针、回调函数、宏定义等高级编程技巧,以及如何利用宏定义提高代码的可读性和可维护性。 5. 库函数和系统调用:详细介绍了C语言标准库函数和一些系统调用的使用方法,如字符串处理函数、数学函数、时间函数等。 6. 多线程和进程:探讨了C语言中多线程和进程的概念和使用方法,包括线程的创建与同步、进程的创建与间通信等。 通过阅读《C语言进阶高级编程PDF》,读者可以拓宽自己的C语言知识面,学习更高级和更复杂的编程技巧,提升自己在C语言编程方面的能力和应用水平。无论是对于初学者还是有一定经验的C语言开发者来说,这本书都是一本很有价值的参考资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值