4.函数指针
函数指针:首先是它是一个指针,它指向的是一个函数
函数名和&函数名:都表示函数的地址
要是想保存函数的地址,就得用到函数指针
p 先跟 * 结合 说明它是指针,后面的一个 () 表示它指向了一个无参的函数,前面的 void 表示返回值 void。
《 C陷阱和缺陷 》 这本书中有这样两个代码:
//代码1 (*(void (*)())0)();
将 0 强制类型转换为 void(*)() 函数指针类型,那么 0 就被当成了一个函数的地址,然后解引用调用,实际上这就是一次函数调用,调用的是 0 作为地址处的函数。
//代码2 void (*signal(int , void(*)(int)))(int);
signal 先跟后面的括号结合,说明 signal 是函数名,函数参数第一个参数是 int,第二个参数是函数指针(该函数指针指向的函数参数是int,返回类型是void),返回值也是一个函数指针,该函数指针指向的函数参数是int,返回类型是void,所以这是一次函数声明。
5.函数指针数组
函数指针数组:首先它是一个数组,数组的每一个元素都是指针指向的是函数。
int(*arr[10])();
首先 arr 先跟 [10] 结合说明它是一个数组,数组中的每一个元素都是 int(*)()类型的函数指针。
函数指针数组的用途:转移表
#include<stdio.h> 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 a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main() { int a, b; int input = 1; int ret = 0; int(*p[5])(int a, int b) = { 0, add, sub, mul, div }; //转移表 while (input) { menu(); printf("请选择:"); scanf("%d", &input); if ((input <= 4 && input >= 1)) { printf("输入操作数:"); scanf("%d %d", &a, &b); ret = (*p[input])(a, b); } else printf("输入有误\n"); printf("ret = %d\n", ret); } return 0; }
6. 指向函数指针数组的指针
指向函数指针数组的指针 :首先它是一个指针,它指向了一个数组,数组中每个元素都是函数指针。
void(*p)();//函数指针 void(*p1[1])();//函数指针数组 void(*(*p2)[2])();//指向函数指针数组指针
7.回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数 的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进 行响应。
qosrt 函数使用:
#include <stdio.h> //qosrt函数的使用者得实现一个比较函数 int int_cmp(const void * p1, const void * p2) { return (*( int *)p1 - *(int *) p2); } int main() { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i = 0; qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);//把一个函数地址传给另一个函数 for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++) { printf( "%d ", arr[i]); } printf("\n"); return 0; }
文章知识点与官方知识档案匹配,可进一步学习相关知识