函数指针:
#include <stdio.h> void test() { ; } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; }
从输出结果可以看出test函数的地址被打印了出来,而且 test 和 &test 结果一样。
既然函数有地址,那么就可以将地址用指针保存起来,这个指针就叫做函数指针,定义方式如:type (*p)();
type是函数的返回值类型,最后面的括号用于存放函数的形参列表。
对函数指针解引用就可以调用这个函数。
单独的函数指针作用不是很直观,但是既然有指针数组,那么就可以将函数指针(地址)存放到数组中
这个数组就叫做函数指针数组。这样一来调用函数就简单的多了。
其定义方式如下:
type (*p[ ])()
*p[ ] 是指针数组,type () 就是一个函数普通函数的定义方式,只不过函数名被省略。
函数指针数组的应用很具有代表性的一个例子就是用转移表实现简易计算器。具体代码请看上一篇博客
扫描二维码关注公众号,回复:
1070835 查看本文章
函数指针数组的指针,一个指针指向一个元素全是函数指针的数组,这个指针就叫做函数指针数组的指针。
下面一段代码加深理解三者定义方式的异同
#include <stdio.h> void test(const char *str) { printf("%s\n", str); } int main() { void (*pfun)(const char *str) = test; //定义函数指针并初始化 void (*pfunArr[5])(const char *str); pfunArr[0] = test; //定义函数指针数组并赋值 void (*(*ppfunArr)[5])(const char *str) = &pfunArr; //定义指向函数指针数组的指针并初始化 return 0; }有一种函数叫做 回调函数,是将一个函数的地址作为参数传给另一个函数,回调函数是在特定的时间或条件发生时由另外一方调用的,就是对某事件的条件相应。一个典型的例子就是 冒泡方式实现qsort
#include <stdio.h> #include <windows.h> int int_cmp(void *p1, void *p2) //将p1,p2强转成整型指针,再解引用进行比较 { return (*(int *)(p1) > *(int *)(p2)); //如果大于,就返回1 } void swap(void *p1, void *p2,int width) //交换函数,函数参数是两个void指针,和需要交换的字节数(元素宽度) { for (int i = 0; i < width; i++) { //按字节交换 *((char *)p1 + i) ^= *((char *)p2 + i); *((char *)p2 + i) ^= *((char *)p1 + i); *((char *)p1 + i) ^= *((char *)p2 + i); } } void bubble(void *base, int size, int width,int(*cmp)(void *p1,void *p2)) { for (int i = 0; i < size; i++) { for (int j = 0; j < size - i - 1; j++) { if (int_cmp((char *)base + j*width, (char *)base + (j + 1)*width)) //将相邻相差width个字节的地址传给cmp函数 { swap((char *)base+j*width,(char *)base+(j+1)*width, width); //若条件满足,则调用swap函数进行交换 } } } } int main() { int arr[] = { 4, 121, 42, 64, 4, 7, 8, 79, 567, 0, 34, 5 }; int size = sizeof(arr) / sizeof(arr[0]); bubble(arr, size, sizeof(int), int_cmp); //调用bubble函数,其参数为首地址,长度,每个元素的宽度,比较函数 for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } system("pause"); return 0; }