之前我们了解了指针,知道如何定义一个指针,接着知道二级指针如何使用。下面我们简单的来回忆一下:
int a = 10; //一个整形变量 int *p = &a; //一个指向整形的指针 int **q = &p; //q是一个指向p的指针,即它是一个指向整形的指针的指针
在这里我们要认识一个新的指针,函数指针,即指向函数的指针。例:
int (*fun)(); //fun是函数指针,它所指向的函数返回值为整形
解析:我们首先要知道这是一个声明,其中这两个花括号也代表了不同的含义。第二个花括号是函数调用操作符,第一个花括号中间接访问操作符迫使间接访问在函数调用之前进行,因此这里使fun成为一个函数指针,它所指向的函数返回值为整形。
int *(*fun)(); //fun是函数指针,它所指向的函数返回值为整形指针
与上述声明不同的是,返回值不同。
int *fun[10]; //一个包含10个元素的指针数组 int (*fun[10])(); //fun为函数指针,指向10个元素的数组
为了使声明更加明确,我们一般会把函数的参数加上,使用完整的函数原型。例:
int (*fun)(int , char); int (*fun[10])(int ,char);
下面我们来讲一讲函数指针的应用吧!
最常见的两个用途是回调函数和转换表。
回调函数:用户把一个函数指针作为参数传递给其他函数,后者将回调用户的函数。
在这里,我们用冒泡排序的方法来实现一下字符串,整形数组的比较吧。
#include<stdio.h>
#include<string.h>
int int_cmp(void *a1, void *a2) //整形数组的比较
{
return *(int *)a1-*(int *)a2;
}
int str_cmp(void *s1, void *s2) //字符串的比较
{
return strcmp((char *)*(int *)s1,(char *)*(int *)s2);
}
void swap(void *p, void *q, int size) //将两值交换
{ //我们需要交换函数作用于任何类型的值,因此把参数
int i = 0; 声明为(void *),一个指向未知类型的指针
char tmp;
for(i = 0;i < size;i++)
{
tmp = *((char*)p+i);
*((char*)p+i) =*((char*)q+i);
*((char*)q+i) = tmp;
}
}
void bubble(void *ptr, int size , int len ,int(*cmp)(void *p,void *q)) //冒泡排序
{
int i = 0,j = 0;
for(i = 0;i < size-1;i++)
{
for(j = 0;j <size-1-i;j++)
{
if(cmp((char *)ptr+j*len,(char *)ptr+(j+1)*len) > 0)
{
swap((char *)ptr+j*len,(char *)ptr+(j+1)*len,len);
}
}
}
}
int main()
{
int arr[]={1,3,4,5,7,8,9,6,2,10};
char *str[]= {"ddddd","ccccd","bbbbb","aasas","bbbbd"};
int i=0 ;
int size = sizeof(arr)/sizeof(arr[0]);
int sz = sizeof(str)/sizeof(str[0]);
bubble(arr, size, sizeof(int), int_cmp); //回调函数int_cmp
for(i = 0;i < size;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
bubble(str,sz,sizeof(char *),str_cmp); //回调函数str_cmp
for(i = 0;i <sz;i++)
{
printf("%s\n",str[i]);
}
return 0;
}转移表:在这里,我们可以用转移表来实现一个袖珍式计算器。比如原始的计算器函数可以写为:
#include<stdio.h>
#include<stdlib.h>
enum jl
{
EXIT,
ADD,
SUB,
MUL,
DIV
};
void menu()
{
printf(" 1.add 2.sub\n");
printf(" 3.mul 4.div\n");
printf(" 0.exit \n");
}
int _add(int num1,int num2)
{
return num1 + num2;
}
int _sub(int num1,int num2)
{
return num1 - num2;
}
int _mul(int num1,int num2)
{
return num1 * num2;
}
int _div(int num1,int num2)
{
return num1 / num2;
}
int main()
{
int select = 1;
int ret = 0;
int num1 = 0,num2 = 0;
while(select)
{
menu();
printf("请选择:\n");
scanf("%d",&select);
if(select != 0)
{
printf("请输入两个整数:\n");
scanf("%d%d",&num1,&num2);
}
switch(select)
{
case ADD:
ret = _add( num1, num2);
break;
case SUB:
ret = _sub( num1, num2);
break;
case MUL:
ret = _mul( num1, num2);
break;
case DIV:
ret = _div( num1, num2);
break;
case EXIT:
exit(1);
break;
}
printf("ret = %d\n",ret );
}
return 0;
}而知道了转移表后,我们可以这样写:
#include<stdio.h>
#include<stdlib.h>
void menu()
{
printf(" 1.add 2.sub\n");
printf(" 3.mul 4.div\n");
printf(" 0.exit \n");
}
int _add(int num1,int num2)
{
return num1 + num2;
}
int _sub(int num1,int num2)
{
return num1 - num2;
}
int _mul(int num1,int num2)
{
return num1 * num2;
}
int _div(int num1,int num2)
{
return num1 / num2;
}
int main()
{
int (*fun[5])(int ,int ) = {0, _add, _sub, _mul, _div};
int select = 1;
int ret = 0;
int num1 = 0,num2 = 0;
while(select)
{
menu();
printf("请选择:\n");
scanf("%d",&select);
if(select != 0)
{
printf("请输入两个整数:\n");
scanf("%d%d",&num1,&num2);
ret = fun[select](num1,num2);
printf("ret = %d\n",ret );
}
}
return 0;
}在这里,转移表就是一个函数指针数组。对于函数指针,大家肯定有了新的认识吧。
原文:http://baixu.blog.51cto.com/10798719/1720569