原创 C声明函数指针并实现回调

2009-11-26 20:39 3088 7 8 分类: 软件与OS
 声明函数指针

    
回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。请看下面的例子:

void f()
// 函数原型

上面的语句声明了一个函数,没有输入参数并返回void。那么函数指针的声明方法如下:

void (*) ();

    
让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:

//
获得函数指针的大小
unsigned psize = sizeof (void (*) ());

//
为函数指针声明类型定义
typedef void (*pfv) ();

pfv
是一个函数指针,它指向的函数没有输入参数,返回类行为void。使用这个类型定义名可以隐藏复杂的函数指针语法。

指针变量应该有一个变量名:

void (*p) (); //p
是指向某函数的指针

    p
是指向某函数的指针,该函数无输入参数,返回值的类型为void。左边圆括弧里星号后的就是指针变量名。有了指针变量便可以赋值,值的内容是署名匹配的函数名和返回类型。例如:

void func()
{
/* do something */
}
p = func;

p
的赋值可以不同,但一定要是函数的地址,并且署名和返回类型相同。

传递回调函数的地址给调用者

    
现在可以将p传递给另一个函数(调用者)- caller(),它将调用p指向的函数,而此函数名是未知的:

void caller(void(*ptr)())
{
ptr(); /*
调用ptr指向的函数 */
}
void func();
int main()
{
p = func;
caller(p); /*
传递函数地址到调用者 */
}

    
如果赋了不同的值给p(不同函数地址),那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。

调用规范

    
到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。如在Visual C++中,可以在函数类型前加_cdecl_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。C++ Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。

    
将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:

//
被调用函数是以int为参数,以int为返回值
__stdcall int callee(int);

//
调用函数以函数指针为参数
void caller( __cdecl int(*ptr)(int));

//
p中企图存储被调用函数地址的非法操作
__cdecl int(*p)(int) = callee; //
出错


    
指针pcallee()的类型不兼容,因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列。

文章评论1条评论)

登录后参与讨论

用户232631 2009-11-28 23:07

学习了

用户569053 2009-5-22 18:00

谢谢分享

用户222792 2009-5-13 01:05

可是好像下不了哦 可以发到我邮箱吗cjxwsz@163.com 不胜感激!

用户222792 2009-5-13 00:53

好多很好的资料啊 怎么没人顶呢! 赞一个! 谢谢你的分享哦 适合我们这些新人! 非常感谢1
相关推荐阅读
pjallen_861848674 2014-02-23 16:25
码间干扰(ISI)
码间干扰是由于有限信道带宽决定的,当信号在有限带宽信道中传输时,在时域会有拖尾,如果拖尾在其它符号抽样处不为0,则造成码间干扰(ISI)。   参考于博士的《信号完整性揭秘:于博士SI设计...
pjallen_861848674 2010-11-02 22:58
MOSFET设计要点1
         最近公司要搞开关电源,所以认真学习MOSFET驱动技术!!呵呵!!!功率MOSFET具有导通电阻低、负载电流大的优点,因而非常适合用作开关电源和整流器件用。设计笔记有以下几点吧:一、...
pjallen_861848674 2010-05-17 17:10
电源完整性设计详解
电源完整性设计详解作者:于争 博士 2009 年 4 月 10 日 目  录  1  为什么要重视电源噪声问题?...............................................
pjallen_861848674 2009-11-27 16:31
TL431原理及应用
  TL431简介及应用 德州仪器公司(TI)生产的TL431是一是一个有良好的热稳定性能的三端可调分流基准源。它的输出电压用两个电阻就可以任意地设置到从Vref(2.5V)到36V范围内的任何值(如...
我要评论
1
7
关闭 站长推荐上一条 /2 下一条