关键词怎么优化到百度首页,长沙财优化公司,龙泉建设工程有限公司网站,免费广告推广网站指针进阶 5.函数指针6. 函数指针数组7. 指向函数指针数组的指针8. 回调函数案例#xff1a;使用回调函数#xff0c;模拟实现qsort#xff08;采用冒泡的方式#xff09;。案例#xff1a;测试qsort排序结构体数据 5.函数指针
补#xff1a; 函数名就是函数的地址 … 指针进阶 5.函数指针6. 函数指针数组7. 指向函数指针数组的指针8. 回调函数案例使用回调函数模拟实现qsort采用冒泡的方式。案例测试qsort排序结构体数据 5.函数指针
补 函数名就是函数的地址 函数名也是函数的地址
代码演示
#includestdio.h
int Add(int x, int y)
{return x y;
}
int main()
{//函数名就是函数的地址//函数名也是函数的地址printf(%p\n, Add);printf(%p\n, Add);
}运行结果: #includestdio.h
int Add(int x, int y)
{return x y;
}
int main()
{//函数指针变量int (*pf1)(int, int) Add;//pf1就是函数指针变量//形式1int (* pf2)(int, int) Add;int ret (* pf2)(2, 3);//形式2int (* pf2)(int, int) Add;int ret pf2(2, 3);//形式3int (* pf2)(int, int) Add;int ret Add(2, 3);printf(%d\n, ret);return 0;
}来看以下两个代码
//代码1
(* (void (*)( )) 0 )( );
//代码2
void (* signal (int , void(*)(int)) )(int);分析 //代码一 将0强制类型转化为(void (*)( ))解引用函数指针类型出入参数为空 //代码二 是一次函数声明,声明的是signal函数 第一个是int类型 第二个是函数指针类型该类型是void( * )(int)。该函数指针指向的函数参数是int返回类型是void signal函数的返回类型也是函数指针类型该类型是void( * )(int),该函数指针指向的函数参数是int,返回类型是void 代码2太复杂如何简化
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);6. 函数指针数组
数组是一个存放相同类型数据的存储空间那我们已经学习了指针数组
//比如
int *arr[10];
//数组的每个元素是int*那要把函数的地址存到一个数组中那这个数组就叫函数指针数组那函数指针的数组如何定义呢
int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];答案是parr1 分析 parr1 先和 [ ] 结合说明 parr1是数组数组的内容是什么呢 是 int (*)( ) 类型的函数指针。 看如下代码进一步理解函数指针数组
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) Sub;//数组中存放类型相同的多个元素int (*pfArr[4])(int, int) { Add, Sub };//pfArr 是函数指针数组 - 存放函数指针的数组return 0;
}函数指针数组的用途转移表
例子计算器
void menu()
{printf(****************************\n);printf(*** 1. add 2. sub ***\n);printf(*** 3. mul 4. div ***\n);printf(*** 0. exit ***\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 main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请输入选择:);scanf(%d, input);switch (input){case 1:printf(请输入两个操作数》);scanf(%d%d, x, y);ret Add(x, y);printf(%d\n, ret);break;case 2:printf(请输入两个操作数》);scanf(%d%d, x, y);ret Sub(x, y);printf(%d\n, ret);break;case 3:printf(请输入两个操作数》);scanf(%d%d, x, y);ret Mul(x, y);printf(%d\n, ret);break;case 4:printf(请输入两个操作数》);scanf(%d%d, x, y);ret Div(x, y);printf(%d\n, ret);break;case 0:printf(退出游戏);default:printf(输入错误);}} while (input);return 0;
}用函数指针实现
void menu()
{printf(****************************\n);printf(*** 1. add 2. sub ***\n);printf(*** 3. mul 4. div ***\n);printf(*** 0. exit ***\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 main()
{int input 0;int x 0;int y 0;int ret 0;do{menu();printf(请选择:);scanf(%d, input);//函数指针数组 - 转移表int (*pfArr[])(int, int) {NULL, Add, Sub, Mul, Div};// 0 1 2 3 4if (0 input){printf(退出计算器\n);}else if (input 1 input 4){printf(请输入2个操作数:);scanf(%d %d, x, y);ret pfArr[input](x, y);printf(ret %d\n, ret);}else{printf(选择错误重新选择!\n);}} while (input);return 0;
}
7. 指向函数指针数组的指针
指向函数指针数组的指针是一个 指针 指针指向一个 数组 数组的元素都是 函数指针 ; 如何定义
8. 回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针地址作为参数传递给另一个函数当这个指针被用来调用其所指向的函数时我们就说这是回调函数。回调函数不是由该函数的实现方直接调用而是在特定的事件或条件发生时由另外的一方调用的用于对该事件或条件进行响应。
//代码演示
void menu()
{printf(****************************\n);printf(*** 1. add 2. sub ***\n);printf(*** 3. mul 4. div ***\n);printf(*** 0. exit ***\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;
}void calc(int (*pf)(int,int))
{int x 0;int y 0;int ret 0;printf(请输入2个操作数:);scanf(%d %d, x, y);ret pf(x, y);printf(ret %d\n, ret);
}int main()
{int input 0;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);break;}} while (input);return 0;
}看图片理解下回调函数 案例使用回调函数模拟实现qsort采用冒泡的方式。
一般冒泡排序
//代码演示
void print_arr(int arr[], int sz)
{int i 0;for (i 0; i sz; i){printf(%d , arr[i]);}printf(\n);
}void bubble_sort(int arr[], int sz)
{//趟数int i 0;for (i 0; i sz - 1; i){//每一趟冒泡排序的过程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;}}}
}int main()
{//数据int arr[] { 9,8,7,6,5,4,3,2,1,0 };int sz sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);bubble_sort(arr, sz);//冒泡排序print_arr(arr, sz);return 0;
}运行结果 这种冒泡排序缺陷 qsort采用冒泡的方式:
了解以下qsort函数: //代码案例
#include stdlib.h
#include string.h
void print_arr(int arr[], int sz)
{int i 0;for (i 0; i sz; i){printf(%d , arr[i]);}printf(\n);
}
int cmp_int(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}
//测试qsort排序整型数据
void test1()
{int arr[] { 9,8,7,6,5,4,3,2,1,0 };int sz sizeof(arr) / sizeof(arr[0]);print_arr(arr, sz);qsort(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);
}
int main()
{test1();return 0;
}运行结果 补void* 1.void* 类型的指针 - 不能进行解引用操作符也不能进行±整数的操作 2.void* 类型的指针是用来存放任意类型数据的地址 3.void* 无具体类型的指针
代码演示
int main()
{char c w;char* pc c;int a 100;//int* p c;//不可以存放char*类型void* pv c;//存放char*pv a;//存放int*return 0;
}案例测试qsort排序结构体数据
结构体数据怎么比较呢
按照年龄比较
#includestdio.h
#includestdio.h
struct Stu
{char name[20];int age;
};
int cmp_stu_by_age(const void* e1, const void* e2)
{return ((struct Stu*)e1)-age - ((struct Stu*)e2)-age;
}
void test1()
{struct Stu arr[] { {zhanhsan, 20}, {lisi, 30}, {wangwu, 12} };int sz sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}
int main()
{test1();return 0;
}按照名字比较 struct Stu
{char name[20];int age;
};
int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)-name, ((struct Stu*)e2)-name);
}
void test2()
{struct Stu arr[] { {zhanhsan, 20}, {lisi, 30}, {wangwu, 12} };int sz sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main()
{test1();return 0;
}
不知不觉指针进阶二以告一段落。通读全文的你肯定收获满满不久的将来会继续更新指针进阶的内容让我们继续为C语言学习共同奋进!!!