首先引入函数指针的定义:函数指针是一个用来存放函数地址的指针变量,
<>一.下面引入一个例子:
对于上述例子中新建立的函数Add(),有以下几个需要注意的地方:
1.&Add 与 Add在数组中代表不同的意义,但在函数指针中,两者代表的意义相同,即Add以及--->> &Add的形式均代表函数的地址,输出的结果相同。
2.注意函数指针的书写方法,以Add函数为例:,其函数的指针表达形式为: int(*pa)(int,int)=Add; 其中,和数组指针的表达方式相类似,(*pa)表示其为一个指针,(int,int)是传入函数的参数类型,最前面的 int 为该函数的返回值类型;
3.对于函数指针的解引用操作来说, (*pa)()代表函数的调用,上述例子中(*pa)(2,4)即代表将2,4两个参数传入到函数Add中去;
<>二.下面讲解两个代码的含义:
1. (*(void(*)())0)()
//把0强制类型转换成: void(*)()函数指针类型;0就是一个函数的地址;-->调用0地址出的该函数;
2.void(*signal(int, void(*)(int)))(int);
//建立一个函数signal,其包含两个参数,类型分别为int类和一个函数指针,该函数指针指向的参数类型为int,返回值为void;而这个函数的返回类型同样是一个函数指针,该函数指针指向的参数为int,返回类型为void;
-->>下面对该函数类型进行简化: typedef void(* pfun_t)(int),原式可以转换为void pfun_t(int,pfun_t);
<>三.函数指针的解引用
->>以上四种调用方法均可以输出相同的效果,但不建议后面两种;此处的*没有用处;
先引入一个例子:
-->>下面建立一个函数指针数组来存放并调用:
->>如上图,建立的函数指针数组为 int(*parr[4])(int, int) = {Add,Sub,Mul,Div};
则parr[i](2,3)中当i取0,1,2,3时,会分别调用上述四个函数,并打印返回值;
-->>函数指针数组的用途:--转移表--,实现一个计算器,大致代码如下:
了解完指向函数指针的数组的定义,我们再来了解回调函数的含义:
回调函数通过其收到的地址,去回调其地址对应的函数,仍然以上题为例:
其中的Calc就是一个回调函数,其通过接收函数的地址,在函数的内部通过调用这个函数,下面先演试下库函数qsort的内容;该函数的头文件为:#include
->>qsort是一个库函数,其包含的四个参数分别为: 传入的数组首元素地址,待排序数组元素的个数,待排序数组每个元素的大小-单位是字节,函数指针:比较两个元素的所用函数的地址(由函数使用者自己创建);其中,void* e1,以及void* e2为无类型指针,既可以接收int类型变量的地址,又可以接收char类型变量的地址;int(*cmp)(const void*e1,const void*e2)为一个函数指针;
#cmp_int函数的比较对返回值有规定:
#void*类型的指针不可以进行解引用操作,原因是:无法确定具体指针的类型;同样也不能进行加减整数的操作;
-->>下面是对利用qsort进行排序的几个例子:
例1:对一个整形数组arr进行排序
例2:对一个浮点型数组f进行排序;
#重点关注结构体数组在进行比较时的操作方法,与整形和浮点型数组的比较方法不同。
补充:若要比较名字name的大小,不可以直接使用<>=,应该用strcmp函数,记得引用头文件#include
例4:对于结构体数组按不同属性进行排序的一个综合:
创建一个程序,可以进行整形数组,浮点型数组,以及结构体数组的冒泡排序,并打印最终结果;
##其中,对于if (cmp((char*)base + j * width, (char*)base + (j + 1) * width)>0) {Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}的操作,由于不同类型的比较方法不同,所以要将比较方法抽离出来,放一个函数指针,把能进行比较方法的函数地址传进来,根据地址去调用比较函数;其要接收两个参数,即为要进行比较的那两个元素的地址;在函数内部比较结束后,返回值大于0则说明第一个元素大于第二个元素,则进行交换;