目录
一、函数指针变量
1、概念
2、使用
3、typedef关键字
二、函数指针数组
三、转移表
四、回调函数
一、函数指针变量
1、概念
指针所指向函数的返回类型 (*函数指针变量名)(指针指向的参数类型的个数的交代)
函数指针 --- 指向函数的指针
函数指针变量 --- 存放函数的地址
int add(int* x,char y) { return x + y; } char* test(int *p,char ch) { return NULL; } int main() { printf("%p\n",&add); printf("%p\n",add); int arr[5] = {0}; itn (*pa)[5] = &arr; int (*pf)(int,int) = &add; //pf就是函数指针变量 char* (*pt)(int*,char) = &test; return 0; }
2、使用
int add(int x ,int y) { return x + y; } main() { int (*pf)(int ,int) = &add; int r = (*pf)(10,20); //pf是函数指针变量 printf("%d\n",r); int c = add(10,20); printf("%d\n",c) int n = pf(10,20); printf("%d\n",n); return 0; }30 30 30实例1:
int main() { (*(void(*)())0)(); return 0; }把0这个地址强制类型转换为void(*)(),这个0地址处放的函数是:无参,返回类型是void的函数
实例2:
void (*signal(int ,void(*)(int)))(int);这是一次函数的声明,声明的函数叫signal,signal函数有两个参数,第一个参数为int,第二个参数为void(*)(int),返回类型是void
3、typedef关键字
typedef unsigned int uint; typedef int* pint; int main() { unsigned int a = 1; unit b = 1; int * b; pint c; }typedef对数组指针和函数指针类型的重命名不好理解
typedef int(*)[5] parr_t; //X typedef int(*parr_t)[5]; //√ typadef int (*)(int,int) parr_t; //X typedef int(*parr_t)(int,int); //√int (*p1)[5] = &arr; parr_t p2 = &arr; int (*pf1)(int,int) = &add; parr_t pf2 = add;对实例2进行简化:
typedef void(*parr_t)(int); parr_t signal(int,parr_t);
二、函数指针数组
int add(int x, int y) { return x+y; } int sub(int x ,int y) { return x-y; } int main() { int (*pf1)(int,int) = &add; int (*pf2)(int,int) = ⊂ int (*pf3[5])(int,int) = {add,sub}; return 0; }
三、转移表
void menu() { printf("-----计算器-----\n"); printf("-----1.add-----\n"); printf("-----2.sub-----\n"); printf("-----3.mul-----\n"); printf("-----4.div-----\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 main() { do{ menu(); printf("选择;"); scanf("%d",&input); switch(input) { case 1: printf("请输入两个数:\n"); scanf("%d%d",&x,&y); r = add(x,y); printf("%d",r); break; case 2: printf("请输入两个数:\n"); scanf("%d%d",&x,&y); r = sub(x,y); printf("%d",r); break; case 3: printf("请输入两个数:\n"); scanf("%d%d",&x,&y); r = mul(x,y); printf("%d",r); break; case 4: printf("请输入两个数:\n"); scanf("%d%d",&x,&y); r = div(x,y); printf("%d",r); break; case 0: printf("退出\n"); break; default: printf("输入错误\n"); } }while(input); return 0; }这样看这个计算器计算语句重复,代码冗余,则可以使用函数指针数组来解决:
void menu() { printf("-----计算器-----\n"); printf("-----1.add-----\n"); printf("-----2.sub-----\n"); printf("-----3.mul-----\n"); printf("-----4.div-----\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 main() { int input = 0; int x,int y; int r = 0; int (*parr_t)(int,int) = {NULL.add,sub,mul,div}; menu(); printf("选择;"); scanf("%d",&input); if(input >= 1 && input <=4) { printf("请输入两个操作数:\n"); scanf("%d%d",x,y); r = parr_t[input](x,y); printf("%d\n",r); } else if (input == 0) { printf("退出游戏\n"); else { printf("选择错误\n"); } return 0; }这种可以是函数指针任意跳转数组叫做转移表
四、回调函数
把函数指针作为参数传递给另一个函数,当这函数指针用来调用自己指向的函数时就是回调函数
void menu() { printf("-----计算器-----\n"); printf("-----1.add-----\n"); printf("-----2.sub-----\n"); printf("-----3.mul-----\n"); printf("-----4.div-----\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; } void calc(int (*pf)(int,int)) //把函数指针作为另一个函数的参数 { int x =0; int y =0; int r =0; printf("请输入两个操作数:\n"); scanf("%d %d",&x,&y); r = pf(x,y); printf("%d\n",r) } int main() { do{ menu(); printf("选择;"); scanf("%d",&input); switch(input) { case 1: calc(add); break; case 2: calc(sub); break; case 3: calc(mul); break; case 4: calc(div); break; case 0: printf("退出\n"); break; default: printf("输入错误\n"); } }while(input); return 0; }C语言中,也有一个函数内使用回调函数,就做qsort(quick sort快速排序算法)
它可以对任意类型的数据进行排序
void print_arr(in arrp[],int sz) { int i = 0; for(i = 0;i < sz;i++) { printf("%d ",arr[i]); } printf("\n"); } int cmp_int(const * void p1,const * void p2) { return *(int *)p1 - *(int *)p2; //p1和p2取相反的排序序列也会相反 } void test1() { int arr[] = {1,2,3,4,5,6,7,8,9,0}; int sz = sizeof(arr) / sizoef(arr[0]); qsort(arr,sz,sizoef(arr[0]),cmp_int) print_arr(arr,sz); } void cmp_float() { if(*(float*)p1 < *(float *)p2) return -1; else if(*(*float*)p1 > *(float *)p2) return 1; else return 0; } void test2() { int arr[] = {1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,0.0}; int sz = sizeof(arr) / sizoef(arr[0]); qsort(arr,sz,sizoef(arr[0]),cmp_float) print_arr(arr,sz); } struct stu { int age; char name[10]; } void cmp_stu_by_name(const void * p1,const void * p2) { return strcmp((*(sturct *)p1).name,(*(struct *)p1).name); // strcmp(((struct *)p1)->name,((struct *)p2)->name); //另一种 } void cmp_stu_by_age(const void * p1,const void * p2) { return *(int *)p1 - *(int *)p2; } void test3() { struct stu arr[] = {{"zhangsan",18},{"lisi",24},{"wangwu",21}}; int sz = sizoef(arr) / sizeof(arr[0]); qsort(arr,sz,sizoef(arr[0]),cmp_stu_by_name); } void test4() { struct stu arr[] = {{"zhangsan",18},{"lisi",24},{"wangwu",21}}; int sz = sizoef(arr) / sizeof(arr[0]); qsort(arr,sz,sizoef(arr[0]),cmp_stu_by_age); } void test5() { struct stu s = {"lihua",18}; struct stu * p = &s; printf("%d\n",stu.age); printf("%d\n",(*p).age); prtinf("%d\n",p->age); } int main() { test(); return 0; }qsort参数:
void qsort(void* base,size_t num,size_t size,int (*compar)(const void* p1,const void* p2));void * base 下待排序的数组的第一个元素
size_t num base指向的数组的元素个数
size_t size 每个元素的大小,单位是字节
int (*compar)(const void * p1,const void * p2)
函数指针,指向的函数可以比较数组中两个元素
p1指向的元素比p2指向的元素小,返回<0的数字
p1指向的元素比p2指向的元素大,返回>0的数字
p1指向的元素比p2指向的元素相等,返回=0的数字