C语言-函数指针与qsort函数

指针中有一种指针叫做函数指针,即用指针来保存一个函数的地址

下面我们以一个最简单的加法函数举例子

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);
}

了解了这个操作之后,我们要尝试对我们所熟悉的冒泡排序法进行改造

下期见!

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值