不知不觉,指针解析来到了第三篇。本篇想讲的内容是有点高级,也有晦涩。说到高级和晦涩,有些人就不同意了。不就些基础内容嘛,何必用高级一次呢?我想我是假借高级一词,重点在“有点”。我倒不能说有点猥琐,有点恶心吧。
我们都知道,程序中的每个函数都位于内存的某个位置上,所以就存在指向那个位置上的指针。知道了这个道理之后呢,我们来看看以下这些声明是怎么一回事?
int f; // 整型变量,这个鬼都知道
int *f; // 一个指向整型的指针,这个鬼也知道
int f(); // 返回类型为整型的函数
int *f(); // 返回类型为一个指向整型指针的函数
// 以上都很平常,都是正常情况
int (*f)(); // 这是神马?.....这是函数指针,一个返回类型为整型的,不接受输入参数的函数指针
int *(*f)(); // 这个也是函数指针,一个返回类型为指向整型指针的,不接受输入参数的函数指针
int (*f[])(); // 这个有点晕!这是一个数组,其元素是函数指针
int *(*f[])(); // 这也是一个数组,其元素也是函数指针,只是返回类型和上面不一样
指针真是强大,伤不起!
看过上面的声明之后,我们可以进入函数指针的世界了。现在展示一个函数指针最基本的调用:
#include <stdio.h>
void MyFun(int ); // 要调用的函数声明
void (*FunP)(int ); // 声明的函数指针,接受一个int类型的参数,返回值为空的函数指针
int main(int argc, char* argv[])
{
MyFun(1); // 这里将直接调用MyFun函数
FunP = &MyFun; // 将MyFun函数的地址赋给FunP,其实,FunP = MyFun,也可以,好玩吧。
(*FunP)(2); // 这里通过函数指针FunP”变量“来调用MyFun函数,注意变量两字啊。
FunP(3); // 你可以这样调用
}
void MyFun(int x)
{
printf("%d\n",x);
}
最近我发觉,有些东西还是直接贴代码好。不然真不知道怎么表达?囧啊!以上的调用过程显示了函数指针的奥妙啊。基于上面的思路,我们在进行拓展
。我们都知道typedef这个参数,其作用是声明自定义数据类型,配合各种原有数据类型来达到简化编程的目的的类型定义关键字。例如:
typedef char data_type;
这个可帮了大忙了。我修改数据类型之类的,都可以灰常快速的进行。那时牵一发而动全身啊!当然,我现在不说它神马牵一发而动全身的问题。我想让大家看懂下面这个问题:
typedef int (*Pfun) (const char *, const char *); // 这个看起来有点晕吧!
施主莫晕!这样只是定义一个函数指针类型,莫怕莫怕!这个声明引入了 Pfun 类型作为函数指针的同义字,该函数有两个 const char * 类型的参数以及一个 int 类型的返回值。当你适应了这个之后,我想介绍回调函数了。神马是回调函数?用户把一个函数指针做为一个参数传递给其他函数,后者将“回调”用户的函数。尼玛,这个解释够拗口的!直白点就是说与指针函数一致的函数可以通过这个回调动作,让其他函数使用!这个还是有点拗口!
看了下面这个例子就会好多:
#include <stdio.h>
int CompareImpl(void const *a, void const *b ); // 要调用的函数声明
typedef int (*Compare) (void const *, void const *); // 声明的函数指针,接受一个void类型的指针参数,返回值为整型的函数指针
int Equal(int , int , Compare); // 回调函数的入口是Compare,至于怎么Compare那就要看传入的函数是如何了。
int main(int argc, char* argv[])
{
printf("结果为:%d\n", Equal(1, 2, CompareImpl)); // 这里我们传入了CompareImpl,说明在*这个地方时调用CompareImpl函数来进行比较
return 0;
}
int CompareImpl(void const *a, void const *b )
{
if (*(int *)a == *(int *)b) // 这里很好玩,我们将void指针转换成int类型。这个函数就被我们改照成了接受
{
return 1;
}
else
{
return 0;
}
}
int Equal(int a, int b, Compare compare)
{
return compare(&a, &b); // *
}
以上的例子应该是最浅显的回调解释了。如果还是不明白,去翻翻书和放狗出去查查相关的资料了
。以上的compare让大家想起神马呢?我想说,这让我想起了模板!用void指针和函数指针来模拟模板的一些初级功能!
接下来要说的是转移表,这个号称是switch/case杀手!到底怎么杀呢?看看一下的代码对比就知道了:
switch ()
{
case A:
func1(1, 2);
break;
case B:
func2(1, 2);
break;
case C:
func3(1, 2);
break;
case D:
func4(1, 2);
break;
default:
break;
}
// 纳尼,这么长!!
// 现在你可以用这样来代替
void func1(double, double);
void func2(double, double);
void func3(double, double);
void func4(double, double);
void (*pfunc[])(double, double) =
{func1, func2, func3, func4 };
// 调用的时候
pfunc[1](1,2); // 调用的是func2(1, 2)
明眼人就看出来了,这是函数指针数组的应用了。
结了,就说到这里吧!睡觉了。。。。。
参考文献
1. 《C语言程序设计》
2. 《C和指针》
3. 《C专家编程》
4. 百度百科的typdef的解释。