C进阶(2)指针的进阶(3)

目录

复习:

5、函数指针(续上一章)

6、函数指针数组

7、指向函数指针数组的指针

8、回调函数


复习:

指针数组

int *arr[4];
char *ch[5];

数组指针

int arr2[5];
int (*pa)[5]=&arr2;

char *arr3[6];
char *(*p3)[6]=&arr3;

函数指针:
也是一种指针,是指向函数的指针

int test(const char *str)
{
    return 0;
}

printf("%p\n",test);
printf("%p\n",&test);

函数名与&函数名都是函数的地址

int (*pf)(const char*)=test;
(*pf)("abc");
pf("abc");

在调用函数的时候,(*pf)与pf是一样的

5、函数指针(续上一章)

两个有点nb的代码

(*(void(*)())0)();

C进阶(2)指针的进阶(3)_第1张图片

 这是一次函数调用,调用的是0作为地址的函数

1.把0强制类型转换为    无参,返回是void的函数    的地址。

2.调用0地址处的这个函数

void(*signal(int,void(*)(int)))(int);

C进阶(2)指针的进阶(3)_第2张图片

 signal是函数名,以上代码是一次函数声明,声明的signal函数的第一个参数的类型是int ,第二参数的类型是函数指针(该函数指针指向的函数参数是int,返回类型是void),signal函数的返回类型也是一个函数指针。

此代码可以简化

typedef void(*pf_t)(int);
pf_t signal(int ,pf_t);

把void(*)(int)类型重命名为pf_t。

6、函数指针数组

函数指针也是指针,把函数和指针放在数组中,其实就是函数指针数组

C进阶(2)指针的进阶(3)_第3张图片

 使用:

int i=0;
for(i=0;i<4;i++)
{
    int ret=arr[i](8,4);
    printf("%d",ret);
}

函数指针数组的用途:转移表。

7、指向函数指针数组的指针

指向函数指针数组的指针是一个指针

指针指向一个数组,数组的元素都是函数指针

//函数指针数组
int (*pfArr[])(int,int)={0,Add,Sub,Mul,Div};
//指向函数指针数组 的指针
int (*(*ppfArr)[5])(int,int)=&pfArr;

8、回调函数

通过函数指针调用的函数

以一个排序为例:(把9-0变成升序)

1.先给出简易实现的冒泡排序

#define _CRT_SECURE_NO_WARNINGS
#include
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}
int main()
{
	int arr[] = {9,8,7,6,5,4,3,2,1,0};
	//将数组排成升序
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

2.介绍qsort()函数

使用快速排序的思想,实现的一个排序函数

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

解释:

base:排序数据起始位置

num:待排序的数据元素个数

width:待排序的数据元素大小,单位是字节

cmp:函数指针-比较函数。

3.用qsort比较数字

#define _CRT_SECURE_NO_WARNINGS
#include
int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	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);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

关于void*不能直接解引用操作的解释:

void*是无具体类型的指针,可能接收任意类型的地址

void*是无具体类型的指针,所以不能解引用操作,也不能+-整数

4.用qosrt比较其他数据类型

#include
struct Stu
{
	char name[20];
	int age;
};
int cmp_stu_by_name(const void* e1, const void* e2)
{
	strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
int main()
{
	struct Stu s[] = { {"zhang san",15},{"lisi",30},{"wangwu",20} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
	for (int i = 0; i < sz; i++)
	{
		printf("%s :", s[i].name);
		printf(" %d\n", s[i].age);
	}
	return 0;
}

5.使用回调函数,模拟实现qsort用冒泡的方式

#include
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;
		int flag = 1;
		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);
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}

int cmp_int(const void* e1, const void* e2)
{
	return (*(int*)e1 - *(int*)e2);
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

你可能感兴趣的:(#,C学习,c语言,c++,算法)