指向函数指针数组的指针与回调函数

int (*p) (int, int);//函数指针
int (*p2[4]) (int, int); //函数指针数组
int (*(*p3)[4])(int, int) = &p2; //取出的是函数指针数组的地址
//p3就是一个指向【函数指针的数组】的指针

从上面代码可以看出:

1. 定义:指向函数指针数组的指针是一个指针,指针指向一个数组,数组的元素都是函数指针;

2. 如何定义?

转移表——函数指针数组

void test(const char* str)
{
printf ("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;

//函数指针的数组pfunArr
void (*pfunArr[5])(const char*);
pfunArr[0] = test;

//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[5])(const char *) = &pfunArr;

 3. 回调函数

回调函数是一个通过函数指针调用的函数

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

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

4.回调函数的使用

举例1

#include <stdio.h>
void menu()
{
	printf("*********************************\n");
	printf("*************请选择:*************\n");
	printf("*************1.加法**************\n");
	printf("*************2.减法**************\n");
	printf("*************3.乘法**************\n");
	printf("*************4.除法**************\n");
	printf("*************0.退出**************\n");
	printf("*********************************\n");
}
int Add(int x, int y)
{
	return x + y;
}

int Sub(int x, int y)
{
	return x - y;
}

int Mul(int x, int y)
{
	return x * y;
}

int Div(int x, int y)
{
	return x / y;
}

int Calc(int (*pf) (int, int))
{
	int x = 0;
	int y = 0;
	printf("请输入2个操作数:>");
	scanf_s("%d %d", &x, &y);
	return pf(x, y);
}

int main()
{
	menu();
	int input = 0;
	int ret = 0;
	printf("请选择:>");
	scanf_s("%d", &input);
	switch (input)
	{
	case 1:
		ret = Calc(Add);
		printf("ret=%d\n", ret);
		break;
	case 2:
		ret = Calc(Sub);
		printf("ret=%d\n", ret);
		break;
	case 3:
		ret = Calc(Mul);
		printf("ret=%d\n", ret);
		break;
	case 4:
		ret = Calc(Div);
		printf("ret=%d\n", ret);
		break;
	case 0:
		printf("退出程序\n");
		break;
	default:
		printf("选择错误,请重新选择\n");

		return 0;
	}
}

冒泡排序: 涉及到函数指针的调用

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//函数qsort介绍
//void qsort(void* base,size_t num,size_t size,int(*compar)(const void*,const void*));
//base中存放的是待排序数据中第一个对象的地址
//size_t num中cunf排序数据元素的个数
//size_t size中存放一个元素的大小,单位是字节
//int(*compar)(const void*,const void*))比较待排序数据中的2个元素的函数

int cmp_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}
void printf_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz;i++)
	{
		printf("%d", arr[i]);
	}
	printf("\n");
}
void test1()
{
	//整形数组的排序
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	printf_arr(arr, sz);
}
struct Stu
{ 
	char name[20];
	int age;
};
int cmp_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);
}
void test2()
{
	//使用qsort函数排序结构体数据
	struct Stu s[] = { {"zhangsan",30},{"lisi",32},{"wangwu",20} };
	int sz = sizeof(s) / sizeof(s[0]);
	//按照年龄来排序
	//qsort(s, sz, sizeof(s[0]), cmp_age);
	//按照名字来排序
	qsort(s, sz, sizeof(s[0]), cmp_name);
}
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++;
	}
}
//实现bubble_sort函数的程序员,他不知道未来排序的数据类型
//程序员也不知道,待比较的两个元素的类型
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*e1, 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 test3()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//使用bubble_sort的程序员一定知道自己排序的是什么数据
	//就应该知道如何比较待排序数组中的元素
	bubble_sort(arr,sz,sizeof(arr[0]),cmp_int);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
}
void test4()
{
	//使用qsort函数排序结构体数据
	struct Stu s[] = { {"zhangsan",30},{"lisi",32},{"wangwu",20} };
	int sz = sizeof(s) / sizeof(s[0]);
	//按照年龄来排序
	//bubble_sort(s, sz, sizeof(s[0]), cmp_age);
	//按照名字来排序
	bubble_sort(s, sz, sizeof(s[0]), cmp_name);
	int i = 0;
	for(i=0;i<sz;i++ )
	{
		printf("%s,%d\n", s[i].name, s[i].age);
	}
}
int main()
{
	//test1();
	//test2();
	//test3();
	test4();
	return 0;
}

对定义的bubble_sort()函数的几点说明:

1. 函数的第一个参数传递的是指向一个数组的指针,由于是一个无具体类型的指针void*,这种指针的特点是能够接受任意类型的指针,void*这种指针不能解引用,不能++或者--操作;

2. 函数中第二个参数是数组中元素的个数

3. 函数中第三个参数是数组中一个元素所占内存的大小,单位是字节

4. 函数中第四个参数是数组中两个元素进行比较的函数指针*cmp,该指针*cmp指向的比较函数需要用户自己定义;该比较函数的两个参数是指向要进行比较的两个元素的指针,指针的类型也是void*,可以接收任意类型的指针;

(1)在bubble_sort函数中对cmp进行传参的时候,base进行了char*的强制类型转换,原因是为了能够跳过j个width的元素,不断让相邻两个元素进行比较;

(2)Swap函数,不仅要传入要交换的两个元素,还需要传入width,这样才能把这个元素中的每一对字节里存的数据交换到,因为base被强转成了char*的类型,交换一次只能交换一对字节的数据;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值