`

声明函数指针并实现回调

 
阅读更多
<script src="http://wz.csdn.net/javascripts/vote.js" type="text/javascript"></script>

程序员常常需要实现回调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调。注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论)。

<!--jcstart-->

声明函数指针

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

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; // 出错


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

分享到:
评论

相关推荐

    函数指针&回调函数培训讲义

    函数指针&回调函数培训讲义,帮助学习函数指针以及回调函数。

    利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦第一种方式.zip

    利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦第一种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦第一种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦第一种方式利用...

    c++ 函数指针和回调的使用

    里面包含: 普通函数指针,同一个类函数指针,不同类的函数指针的使用。

    mfc下实现回调函数

    程序实现了在mfc下如何定义一个回调函数,如何使用回调函数,以及如何把类指针传递递给用户回调函数的例程。

    回调函数就是一个通过函数指针调用的函数

    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用

    C++ 课程作业 数组指针与字符串1——冒泡排序(函数指针,回调函数)

    本题希望通过回调函数,定义一个冒泡排序函数,可以根据函数指针指向不同的比较函数,分别实现从大到小和从小到大的排序。 希望通过这道题目,可以帮助大家理解函数指针与回调函数。本题较为简单,仅能处理整数的...

    C语言中的回调函数实例

    在C语言中一般用typedef来为回调函数...//pa和pb都是char型指针先看一个回调函数的例子: 代码如下:#include //方法指针的格式为:int (*ptr)(char *p) 即:返回值(指针名)(参数列表)typedef int (*CallBackFun)(char *

    linuxC语言函数指针回调函数教程

    linuxC语言函数指针回调函数教程!很详细。

    python通过ctypes调用c,python向c函数通过结构体传递python回调函数指针,c回调python

    python通过ctypes调用c语言库函数;python向c函数传递二维数组,一维数组,指针灯参数;...python向c以参数形式传结构体指针,结构体内包含c回调python函数指针,且c函数回调结构体指定的python回调函数;

    c++函数指针和回调函数示例

    回调函数其实就是一个通过函数指针调用的函数!假如你把A函数的指针当作参数传给B函数,然后在B函数中通过A函数传进来的这个指针调用A函数,这就是回调机制。B函数就是回调函数。 3.函数指针的使用 3.1函数指针声明 ...

    利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式.zip

    利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式

    C++函数指针和回调函数使用解析

    函数指针变量的声明: typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针变量 实例 以下实例声明了函数指针变量 p,指向函数 max: #include int max(int x, int y){ return x &gt; y ? ...

    CC++中回调函数初探

    本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题,在开始之前,假设你已经熟知了函数指针。    什么是回调函数? 简而言之,回调函数就是一个通过函数指针调用的函数。假如你把函数的...

    利用现成实现的回调函数

    利用Delphi7实现的调用回调函数。与一般回调函数不同,此回调函数调用时利用线程,实现调用回调函数后,不等处理完,立即返回。

    C回调函数,函数回调

    程序员常常需要实现回调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调。注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论)。

    详细理解C指针-指针函数与函数指针和回调函数[整理].pdf

    详细理解C指针-指针函数与函数指针和回调函数[整理].pdf

    C++中回调函数(CallBack)的用法分析

    本文实例分析了C++中回调函数...由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让thi

    BCB线程中调用主界面的回调函数

    网上的回调函数都是API例子,学习函数指针倒是不错,可是很难让初学者立即应用。常见的情况是辅线程完成某事件后需要“通知”主界面,比如常见的进度条——线程中完成一定的进度后即通知主界面显示到一定的刻度。本...

    mfc使用回调函数(系统api)并传入对象指针

    mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象...

    详解C语言编程中的函数指针以及函数回调

    函数指针: 就是存储函数地址的指针,就是指向函数的指针,就是指针存储的值是函数地址,我们可以通过指针可以调用函数。 我们先来定义一个简单的函数: //定义这样一个函数 void easyFunc() { printf("I'm a easy...

Global site tag (gtag.js) - Google Analytics