目录
复习:
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是一样的
两个有点nb的代码
(*(void(*)())0)();
这是一次函数调用,调用的是0作为地址的函数
1.把0强制类型转换为 无参,返回是void的函数 的地址。
2.调用0地址处的这个函数
void(*signal(int,void(*)(int)))(int);
signal是函数名,以上代码是一次函数声明,声明的signal函数的第一个参数的类型是int ,第二参数的类型是函数指针(该函数指针指向的函数参数是int,返回类型是void),signal函数的返回类型也是一个函数指针。
此代码可以简化
typedef void(*pf_t)(int);
pf_t signal(int ,pf_t);
把void(*)(int)类型重命名为pf_t。
函数指针也是指针,把函数和指针放在数组中,其实就是函数指针数组
使用:
int i=0;
for(i=0;i<4;i++)
{
int ret=arr[i](8,4);
printf("%d",ret);
}
函数指针数组的用途:转移表。
指向函数指针数组的指针是一个指针
指针指向一个数组,数组的元素都是函数指针
//函数指针数组
int (*pfArr[])(int,int)={0,Add,Sub,Mul,Div};
//指向函数指针数组 的指针
int (*(*ppfArr)[5])(int,int)=&pfArr;
通过函数指针调用的函数
以一个排序为例:(把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;
}