<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的回调函数,实现调用者和底层驱动的解耦第一种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦第一种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦第一种方式利用...
里面包含: 普通函数指针,同一个类函数指针,不同类的函数指针的使用。
程序实现了在mfc下如何定义一个回调函数,如何使用回调函数,以及如何把类指针传递递给用户回调函数的例程。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用
本题希望通过回调函数,定义一个冒泡排序函数,可以根据函数指针指向不同的比较函数,分别实现从大到小和从小到大的排序。 希望通过这道题目,可以帮助大家理解函数指针与回调函数。本题较为简单,仅能处理整数的...
在C语言中一般用typedef来为回调函数...//pa和pb都是char型指针先看一个回调函数的例子: 代码如下:#include //方法指针的格式为:int (*ptr)(char *p) 即:返回值(指针名)(参数列表)typedef int (*CallBackFun)(char *
linuxC语言函数指针回调函数教程!很详细。
python通过ctypes调用c语言库函数;python向c函数传递二维数组,一维数组,指针灯参数;...python向c以参数形式传结构体指针,结构体内包含c回调python函数指针,且c函数回调结构体指定的python回调函数;
回调函数其实就是一个通过函数指针调用的函数!假如你把A函数的指针当作参数传给B函数,然后在B函数中通过A函数传进来的这个指针调用A函数,这就是回调机制。B函数就是回调函数。 3.函数指针的使用 3.1函数指针声明 ...
利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式利用函数指针实现C的回调函数,实现调用者和底层驱动的解耦 第二种方式
函数指针变量的声明: typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针变量 实例 以下实例声明了函数指针变量 p,指向函数 max: #include int max(int x, int y){ return x > y ? ...
本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题,在开始之前,假设你已经熟知了函数指针。 什么是回调函数? 简而言之,回调函数就是一个通过函数指针调用的函数。假如你把函数的...
利用Delphi7实现的调用回调函数。与一般回调函数不同,此回调函数调用时利用线程,实现调用回调函数后,不等处理完,立即返回。
程序员常常需要实现回调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调。注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论)。
详细理解C指针-指针函数与函数指针和回调函数[整理].pdf
本文实例分析了C++中回调函数...由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让thi
网上的回调函数都是API例子,学习函数指针倒是不错,可是很难让初学者立即应用。常见的情况是辅线程完成某事件后需要“通知”主界面,比如常见的进度条——线程中完成一定的进度后即通知主界面显示到一定的刻度。本...
mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象指针 mfc使用回调函数(系统api)并传入对象...
函数指针: 就是存储函数地址的指针,就是指向函数的指针,就是指针存储的值是函数地址,我们可以通过指针可以调用函数。 我们先来定义一个简单的函数: //定义这样一个函数 void easyFunc() { printf("I'm a easy...