指针中有一种指针叫做函数指针,即用指针来保存一个函数的地址
下面我们以一个最简单的加法函数举例子
int Add(int x,int y)
{
return x+y;
}
int main()
{
int ret=Add(2,3);
return 0;
}
我们要引入函数指针这个概念,我们首先尝试拿出函数的地址
printf("%p ",&Add);
printf("%p ",Add);
我们会发现上面两段代码打印出的结果是一样的
现在我们尝试用一个指针去接受这个函数的地址
int(*pf)(int,int)=&Add;
int(*pf)(int x,int y)=&Add;
//这两种写法均可,那这个函数指针为例子,第一个int是函数的返回类型
//第二个括号内是函数形参的类型,变量写不写都可以
下面我们尝试调用一下这个函数指针
int ret=Add(2,3);//这是常规的调用形式
int ret=(*pf)(2,3);//这是通过函数指针的调用格式,那个*,括号加不加其实都可以
int ret=pf(2,3);//结果是一致的
有了上面的铺垫我们知道,Add也可以不取地址直接打印出函数的地址
这里我们再补充说明一下函数指针数组的概念,即把返回类型一致,参数类型一致的函数封装到同一个函数指针数组中去,还是拿计算器我们举一个例子
int (*pf[4])(int,int)={Add,Sub,Mul,Div};
//这就是把函数指针放到一个数组内部保存,调用的时候方便
比如我们调用加法
int ret=pf[0](2,3);
所以我们无意间调用函数实际是用函数指针进行的操作,但是感觉函数指针的作用不是很大,因为我们直接调用这个函数就好了,但实际上在一个大型的开发项目中,函数指针的作用是巨大的,下面我们介绍一个库函数qsort快速排序函数,简单应用一下函数指针
qsort函数列属于头文件stdlib.h中,使用前要声明
#include<stdlib.h>
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))//这个是qsort函数
//返回类型是void
//第一个参数是指向要排序的数组的第一个元素的指针(数组名)
//第二个参数是比较的数组中的元素个数,第三个参数是数组元素的大小,第四个就是一个函数指针,我们传参的时候要传一个函数
该函数的优点是,可以比较整形,浮点型,字符型,字符串型,结构体类型,功能非常强大,而冒泡排序只能比较整形的大小
下面我们应用qsort函数来比较两个整形的大小
#include<stdio.h>
int cmp(const void* e1,const void* e2)//比较整形
{
if(*(int*)e1>*(int*)e2)
return 1;
else if(*(int*)e1==*(int*)e2)
return 0;
else
return -1;
}
//返回值的要求qsort函数有规定
int cmp_plus(const void*e1,const void*e2)
{
return ((*(int*)e1-*(int*)e2));
}
int main()
{
int arr[5]={5,9,6,7,3};
qsort(arr,sizeof(arr)/sizeof(arr[0]),sizeof(arr[0]),cmp);
}//这里的qsort函数本身其实也就是一个回调函数,在函数传参的过程中传入了另外一个函数
//作为该函数的参数进行调用
下面我们尝试比较两个字符串的大小(创建指针数组来存储字符串)
char* s[3]={"java","cpp","golong"};
int cmp_str(const void* e1,const void* e2)//比较字符串大小
{
return strcmp((char*)e1,(char*)e2);
}
int cmo_str_len(const void* e1,const void* e2)//比较字符串长度
{
return strlen((char*)e1)-strlen((char*)e2);
}
int main()
{
qsort(s,sizeof(s)/sizeof(s[0]),sizeof(s[0]),cmp_str);
qsort(s,sizeof(s)/sizeof(s[0]),sizeof(s[0]),cmp_str_len);
return 0;
}
下面我们尝试用qsort来比较结构体类型的数据
#include<stdio.h>
#include<stdlib.h>//调用qsort函数
#include<string.h>//调用strcmp函数
struct stu
{
char name[64];
int age;
}
int cmp_stu_age(const void*e1,const void* e2)
{
return ((struct stu*)e1)->age-((struct stu*)e2)->age;
}//这里是设计一个函数来比较结构体内部年龄的数据
int cmp_stu_name(const void*e1,const void* e2)
{
return strcmp(((struct stu*)e1)->name,((struct stu*)e2)->name);
}//下面解释一下为什么可以直接使用strcmp函数,因为这个函数的返回类型的情况
//跟我们需要的一致
int main()
{
struct stu s[3]={{"java",23},{"golong",21},{"cpp",35}};
int s_len=sizeof(s)/sizeof(s[0]);
qsort(s,s_len,sizeof(s[0]),cmp_stu_name);
}
了解了这个操作之后,我们要尝试对我们所熟悉的冒泡排序法进行改造
下期见!