# 本篇博客主要阐述回调函数,函数指针的概念,并且使用回调函数实现冒泡排序,可以
实现不同数据类型的排序。
接下来就切入正题吧!
# 概念阐述(概念部分比较枯燥,但是想要理解那么就很有必要阅读)
一
个
函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接
调
用,
而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
(在《C和指针》 p 261,有提到回调函数);
-----百度百科
@函数指针
: int (*fun)(char *);
数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函
数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做
函数的参数。
----百度百科
@看了函数指针的概念那么就有人问了,会不会和数组指针指针数组一样,还有个指针函数,又是否和函数
指
针一样呢? 那么我们下来就分析一下,函数指针和指针函数的区别!
(关于指针数组和数组指针的介绍http://blog.csdn.net/bitboss/article/details/51261200点击打开链接)
@ 指针函数
: int * fun( int , char );
指针函数是指返回值是指针的函数,即本质是一个函数;即我们平常写的函数基本都有返回值,只不过
指针函数返回类型是某一类型的指针;
(
而函数指针则是指向一个函数的指针变量;所以两者是有本质的区别的;)
@函数指针数组
void ( *pfun[3] )( int ) = { 0 };
: 定义一个数组,数组中每个元素为一个函数指针,有点像指针数组;注意数组的类型!
# void* (*signal( int , void* (*) ( int ) ) ) ( int ) ;
/*
大家看上面这个代码,思考一下这句代码的含义;(引自《C陷阱与缺陷》第二章 略微修改);
如果可以看懂上面这个指针函数和函数指针的糅合体,那么下面的内容将会很好理解! 将在本篇博客末尾做出最
本段代码的理解!
*/
#那么下面开始第一个小的知识点!
1.
#include<stdio.h>
void fun();
int main()
{
fun();
*fun();
****fun();
}
/*
大家可以试着实现一下这个代码,看看编译器会不会报错,有没有警告,实际上这三句代码的意义是一样的!都只是
对函数 fun 的调用; 下面这个代码或许可以帮助你理解;
*/
2.
#include<stdio.h>
void fun();
int main()
{
printf("%p\n",fun);
printf("%x\n",&fun);
return 0;
}
ps:结果我就不在这里展示了,大家可以自己敲敲,看看结果是否一样!
3.
#下面列出一个简单的函数指针数组的应用,帮助理解函数指针通过数组的运用。
#include<stdio.h>
void fun1(char *str1)
{
printf("fun1:%s\n",str1);
}
void fun2(char *str1)
{
printf("fun2:%s\n",str1);
}
void fun3(char *str1)
{
printf("fun3:%s\n",str1);
}
int main()
{
/*
请注意这块函数指针数组的声明,比函数指针多了个方括号!
*/
void (*pfunarr[3])(char *) = {0};
//void (*)(char *) 就是这个函数指针数组的类型!
int i = 0;
pfunarr[0] = fun1;
pfunarr[1] = fun2;
pfunarr[2] = fun3;
for(i=0; i<3; i++)
{
pfunarr[i]("hello");
}
return 0;
}
# 看了上面的内容,相信大家对回调函数使用的基本要素都有所了解了,那么接下来就是重头戏了;
4.
#使用回调函数实现冒牌排序,可以排序不同类型的数据!
# 关于冒泡排序的概念和两种单独类型的实现方法在这篇博客中有详细提到!
(点击打开链接http://blog.csdn.net/bitboss/article/details/51192704
冒泡排序实现整形数组和字符串数组)
所以,在这里我们直接展示使用回调函数的实现方法!(代码借鉴 CSDN红黑联盟 #发现自己写的太挫)
完成回调函数实现冒泡排序字符串或数字:
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
函数功能:以char类型交换两个元素,大小为size。
*/
void swap(char *p1,char *p2,int size)
{
int i = 0;
char tmp = 0;
for(i = 0;i<size;i++)
{
tmp = *(p1+i);
*(p1+i) = *(p2+i);
*(p2+i) = tmp;
}
}
/*
函数功能:比较整数的回调函数。
*/
int compare_int(const void *elem1,const void *elem2)
{
return (*(int *)elem1) - (*(int *)elem2);
}
/*
函数功能:比较字符串的回调函数。
*/
int compare_str(const void *elem1,const void *elem2)
{
return strcmp((char *)(*(int *)elem1), (char *)(*(int *)elem2));
}
/*
函数功能:冒泡排序函数。
*/
void bubble_str_int(void *base,int size,int width,int ( *cmp )(const void *elem1, const void *elem2 ))
{
int i = 0;
int j = 0;
for(i = 0;i<size-1;i++)
{
for(j = 0;j<size-i-1;j++)
{
if(cmp(((char *)base+(j*width)),((char *)base+(j+1)*width))<0)
{
swap((char *)base+(j*width),(char *)base+(j+1)*width,width);
}
}
}
}
int main()
{
char *arr_str[] = {"ddddd","aaaaa","ccccc","bbbbb","zzzzz"};
int arr_int[] = {1,3,5,7,9,2,4,6,8,10};
int i = 0;
int size_int = sizeof(arr_int)/sizeof(arr_int[0]);
int size_str = sizeof(arr_str)/sizeof(arr_str[0]);
bubble_str_int(arr_int,size_int,sizeof(arr_int[0]),compare_int);
printf("bubble_sort int:\n");
for(i = 0;i<size_int;i++)
{
printf("%d ",arr_int[i]);
}
printf("\n");
bubble_str_int(arr_str,size_str,sizeof(arr_str[0]),compare_str);
printf("bubble_sort string:\n");
for(i = 0;i<size_str;i++)
{
printf("%s\n",arr_str[i]);
}
system("pause");
return 0;
}
# 实现方法是模拟的qsort函数
(库函数中 qsort 函数就是回调函数的经典例子,有兴趣的同学可以在库函数中去看一下 qsort 的实现,这里只实现
使用回调函数实现冒泡排序;)
/*
如果大家想要代码运行看起来更美观,可以在开始用 printf 打印一些菜单,同时调用cmp 函数是可以创建一个函数指针数组保存函数指针,通过枚举列出需要排序的菜单,简
单的应用一下函数指针数组,当然,还有很多可以完善的地方,我这里就只有基本的解题思路了,大家 可以自己下来完善!
*/
5.那么,本篇文章就到了最后了,也就剩最后一个问题了;
# void* (*signal( int , void* (*) ( int ) ) ) ( int ) ;
# 分析时,我们把这段代码分开看,我是从里到外看的, 因为()的优先级比 ' * '高,所以先看 void* (*)( int ); 这是
个函数指针,大家应该可以认出来吧,然后它的外面是 signal,所以 这个函数指针和一个 int 型数据作为参数被 signal
函数调用, void* ( * ) ( int ) ; 当把属于signal 的部分取出来时,剩余的部分又是一个函数指针的声明;那么就说明,
signal 函数调用的结果又作为一个函数指针变量被声明;
所以,这个表达式的意义就是声明一个指针变量,它的返回值是 void* 参数是 int 的函数指针;
博客写的比较杂乱,希望大家指出错误和不足!
谢谢!