指针进阶
- 5. 函数指针
- 6. 函数指针数组
- 7. 指向函数指针数组的指针
- 8. 回调函数
10.1 指针进阶_数组指针
10.3 指针进阶_代码分析
5. 函数指针
void test()
{printf("hehe\n");
}
int main()
{printf("%p\n", test);printf("%p\n", &test);return 0;
}
006013B6
006013B6
test和&test都是函数地址
eg
void test(char* pc, int arr[10])
{ }
int main()
{void (*pf)(char*, int arr[]) = test;return 0;
}
eg
int Add(int x, int y)
{return x + y;
}
int main()
{int arr[10] = { 0 };int(*pa)[10] = &arr;//类比int(*pf)(int, int) = &Add;//pf是函数指针变量return 0;
}
使用指针调用函数
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf)(int, int) = &Add;int r = Add(3, 5);printf("%d\n", r);int m = (*pf)(4, 5);//--> int m = pf(4, 5);//pf和Add一回事printf("%d\n", m);return 0;
}
eg1.代码分析
(*(void (*)())0)();void (*p)()-->p是函数指针
void (*)() -->函数指针类型
(void (*)())0-->强制类型转换, 0转换成 void (*)(), 0的地址中存放着这个函数
*(void (*)())0-->解引用,调用这个函数
(*(void (*)())0)()-->调用时无参数
(*(void (*)())0)();-->调用0地址处的函数
eg2.代码分析
void (*signal(int , void(*)(int)))(int);void (*p)(int); -->函数指针
void(*)(int)-->函数指针指向一个int类型的参数,返回类型void
signal(int , void(*)(int))--> signal 函数(类型 int ,函数指针类型 void(*)(int))
简化
//typedef重定义
typedef unsigned int uint;
typedef int* ptr_t;typedef int(*parr_t)[10];
typedef int(*pf_t)(int,int);int main()
{uint u1;ptr_t p1;int* p2;return 0;
}
void (*signal(int , void(*)(int)))(int);
--->typedef void(*pf_yt)(int);//void (*signal(int, void(*)(int)))(int);pf_yt signal(int, pf_yt);
6. 函数指针数组
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(*pf1)(int, int) = Add;//int(*pf2)(int, int) = Sub;//int(*pf3)(int, int) = Mul;//int(*pf4)(int, int) = Div;//函数指针数组int (*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };int input = 0;int x = 0;int y = 0;int ret = 0;printf("1.Add 2.Sub 3.Mul 4.Div\n");scanf("%d", &input);printf("输入两个操作数\n");scanf("%d %d", &x, &y);ret = pfArr[input](x, y);printf("ret = %d\n", ret);return 0;
}
7. 指向函数指针数组的指针
int (*pf)(int, int);//函数指针
int (*pfArr[4])(int, int);//函数指针数组pfArr
int (*(*p)[4])(int, int) = &pfArr;//函数指针 数组的地址
//p就是指向函数指针数组的指针
8. 回调函数
回调函数:通过函数指针调用的函数。
把函数的指针(地址)作为参数传递给另一个函数,指针被用来调用其所指向的函数。
回调函数不是由该函数的实现方直接调用,而是由另外的一方调用的。
void menu() {printf("* 1.add 2.sub *\n");printf("* 3.mul 4.div *\n");printf("* 0.exit *\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("输入两个操作数\n");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}
int main() {int input = 0;int x = 0;int y = 0;int ret = 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
函数用来排序
qsort
- 快速排序
- 适合任意类型
void qsort( void* base,//指向需要排序数组的第一个元素size_t num,//排序的元素个数size_t width,//一个元素的大小,单位是字节int(__cdecl* compare)(const void* elem1, const void* elem2)//函数指针类型);
viod* -->无具体类型指针,可以接收任意类型的地址。
不能直接解引用,不能直接进行指针运算。
因为不知道类型,不知道访问多少字节空间。
#include <stdlib.h>
//qsort排序整形
int cmp_int(const void* p1, const void* p2) {return(*(int*)p1 - *(int*)p2);
}
void print(int arr[], int sz){int i = 0;for (i -= 0; i < sz; i++) {printf("%d ", arr[i]);}
}
test1() {int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);//qsort默认是升序qsort(arr, sz, sizeof(arr[0]), cmp_int);print(arr, sz);
}
int main() {test1();return 0;
}
0 1 2 3 4 5 6 7 8 9
//qsort排序结构体数据_age
struct Stu {char name[20];int age;
};
int cmp_stu_by_age(const void* p1, const void* p2) {return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
void test2() {struct Stu arr[] = { {"alice",30},{"bob",20},{"ruarua",10} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}
int main() {//test1();test2();return 0;
}
名称 | 值 | 类型 |
---|---|---|
arr | 0x009af81c {{name=0x006ff7ac “alice” age=30 }, {name=0x006ff7c4 “bob” age=20 }, {name=0x006ff7dc “ruarua” …}} | Stu[3] |
[0] | {name=0x006ff7ac"alice" age=30 } | Stu |
[1] | {name=0x006ff7c4 “bob” age=20 } | Stu |
[2] | {name=0x006ff7dc “ruarua” age=10 } | Stu |
–> |
名称 | 值 | 类型 |
---|---|---|
arr | 0x006ff7ac {{name=0x006ff7ac “ruarua” age=10 }, {name=0x006ff7c4 “bob” age=20 }, {name=0x006ff7dc “alice” …}} | Stu[3] |
[0] | {name=0x006ff7ac “ruarua” age=10 } | Stu |
[1] | {name=0x006ff7c4 “bob” age=20 } | Stu |
[2] | {name=0x006ff7dc “alice” age=30 } | Stu |
//qsort排序结构体数据_name
struct Stu {char name[20];int age;
};
int cmp_stu_by_name(const void* p1, const void* p2) {return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
void test3() {struct Stu arr[] = { {"zalice",30},{"tbob",20},{"aruarua",10} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main() {//test1();//test2();test3();return 0;
}
名称 | 值 | 类型 |
---|---|---|
arr | 0x0054f6b4 {{name=0x0054f6b4 “zalice” age=30 }, {name=0x0054f6cc “tbob” age=20 }, {name=0x0054f6e4 “aruarua” …}} | Stu[3] |
[0] | {name=0x0054f6b4 “zalice” age=30 } | Stu |
[1] | {name=0x0054f6cc “tbob” age=20 } | Stu |
[2] | {name=0x0054f6e4 “aruarua” age=10 } | Stu |
–>
名称 | 值 | 类型 |
---|---|---|
arr | 0x0054f6b4 {{name=0x0054f6b4 “aruarua” age=10 }, {name=0x0054f6cc “tbob” age=20 }, {name=0x0054f6e4 “zalice” …}} | Stu[3] |
[0] | {name=0x0054f6b4 “aruarua” age=10 } | Stu |
[1] | {name=0x0054f6cc “tbob” age=20 } | Stu |
[2] | {name=0x0054f6e4 “zalice” age=30 } | Stu |
10.1 指针进阶_数组指针
10.3 指针进阶_代码分析