1. 函数指针函数名 VS &函数名

对于数组而言,数组名=首元素地址,&数组名=整个数组的地址

那么函数名和&函数名等于什么

#include void test(){;}int main(){test();printf("%p\n", test);printf("%p\n", &test);}

注:函数名和&函数名不能+-整数

结论是:函数名和&函数名一样 = 函数的地址

什么是函数指针

既然函数名=函数地址,就可以用一个变量进行存储

这个变量就是函数指针,存储一个函数地址的变量

#include int test(int x, int y){;}int main(){int(*ptr)(int, int) = test; }

这里的ptr就是一个函数指针

(*ptr),表示ptr是一个指针变量 ,(int, int), 表示ptr存储的是一个函数的地址,这个函数有两个int类型的参数,(*ptr)前面的int, 表示这个函数的返回类型为int整形

函数指针的应用

#include int test(int x, int y){return x + y;}int main(){int(*ptr)(int, int) = test;int ret = (*ptr)(1,2);printf("%d\n", ret);}

*ptr表示通过地址访问空间 —> 得到函数的地址 —> 传值(1,2) —> 得到结果3 —> 打印

函数指针作为参数

// 使用冒泡排序,排序任意类型数组#include #include struct Stu{char name[10];int age;};int cmp_int(const void* e1, const void* e2){return *(int*)e1 - *(int*)e2;}// 以年龄比较int cmp_by_name(const void* e1,const void* e2){return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);}// 以名字比较int cmp_by_age(const void* e1, const void* e2){return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;}// 交换void swap(char* buf1, char* buf2, int width){while (width--){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}}// 排序void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2)){int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j  0){swap((char*)base + (j * width), (char*)base + ((j + 1) * width), width);}}}} //排序整形数组void sort_int(){int arr[10] = { 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 < 10; i++){printf("%d ", arr[i]);}}// 排序结构体数组void sort_struct(){struct Stu t1[5] = { {"c",5 }, { "a",4 }, { "b",3 }, { "e",2 }, { "d",1 } };int sz = sizeof(t1) / sizeof(t1[0]);bubble_sort(t1, sz, sizeof(t1[0]), cmp_by_name); // 以名字排序//bubble_sort(t1, sz, sizeof(t1[0]), cmp_by_age);// 以年龄排序}int main(){//sort_int();sort_struct();}

2. 函数指针数组什么是函数指针数组

首先梳理一下概念,数组是一组相同类型元素的集合,函数指针是存储函数地址的变量

所以函数指针数组,就是存储一组函数地址的集合

#include void test1(){;}void test2(){;}void test3(){;}int main(){void(*ptr[3])() = { test1,test2,test3 };}

void (* ptr[3] )() , 如何理解 ?

ptr首先会与[3]结合,表示ptr是一个数组,数组有3个元素

void (* ptr[3] )() —> void (*)(),

(*) 表示数组的每一个元素是一个指针,()表示这个指针是一个函数指针且函数没有参数,void表示函数返回值为空

函数指针数组的应用

#include 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 menu(){printf("1.add2.sub\n");printf("3.mul4.div\n");}int main(){int(*ptr[5])(int, int) = { 0,add,sub,mul,div }; //函数指针数组int input = 0;int x = 0;int y = 0;int ret = 0;do {menu();printf("输入: ");scanf("%d", &input);if (input > 4 || input <= 0){printf("退出程序\n");}else{printf("输入x: ");scanf("%d", &x);printf("输入y: ");scanf("%d", &y);ret = (ptr[input])(x, y); //通过input,锁定函数地址,最后传参得到结果printf("%d\n", ret);}} while (input);}

3. 指向函数指针数组的指针

直接看代码

#include int main(){int arr[10] = { 0 }; // 整形数组int(*pa)[10] = &arr; // 数组指针,指向数组的指针int(*pf[10])(int, int); // 函数指针数组int(*(*ppf)[10])(int,int)= &pf // 指向函数指针数组的地址 }

既然可以用&操作符取出一个整形数组的地址,那么也可以取出一个函数指针数组的地址

所以,指向函数指针数组的指针就是存储整个函数指针数组的地址的变量

int (* (*ppf) [10] ) (int, int) 如何理解 ?

(*ppf), 表示ppf是一个指针, [10]表示这个指针存储一个数组的地址,数组有10个元素,int (*) (int, int), 表示数组的每一个元素是一个函数指针