问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

vc6中如何定义函数指针

发布网友 发布时间:2022-05-18 09:11

我来回答

2个回答

热心网友 时间:2023-10-13 05:10

这里有个比较详细的解释 其实你一搜到处都是 学会自学 学会用msdn
程序员常常需要实现回调。本文将讨论函数指针的基本原则并说明如何使用函数指针实现回调。注意这里针对的是普通的函数,不包括完全依赖于不同语法和语义规则的类成员函数(类成员指针将在另文中讨论)。

声明函数指针

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

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,尽管两者有相同的返回值和参数列。

热心网友 时间:2023-10-13 05:10

类型 *变量名。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
临沂比较有名的男装品牌 呼伦贝尔市悦动网络科技有限公司怎么样? 呼伦贝尔中汇实业有限公司怎么样? 呼伦贝尔油玉不绝电子商务有限公司怎么样? 如何避免wps卡顿? 属鼠的男人找对象是属什么,属鼠的人和什么属相合 96年鼠的姻缘在哪年 属相相合年份运势提升 2024属鼠找对象属什么最佳 黑客攻击网站能报案吗 黑客攻击报案有用吗 c++ 函数指针 和 函数类型的形参 关于函数指针 函数调用(函数指针) 如何定义一个函数指针? 指针函数和指向函数的指针在意义和用法上有什么区别 请问函数指针和指针函数的运用? 函数指针定义 华硕r9 380显卡需要多大的电源 加盟亿爵餐饮开一家一绝披萨店,0经验如何经营好一家一绝披萨门店呢? 如何把多个word文档合并成一个文档 英雄杀中杀、血杀、暗杀有什么区别?? 手游英雄杀和端游有什么区别 三国杀 和英雄杀 哪个好玩有什么区别 英雄杀MVP是什么意思? 关于英雄杀的问题 英雄杀任桓之报数是什么意思? 三国杀与英雄杀的区别 AMDYXS,RTDSYBRXLDS这句话是什么意思 一个人的个性签名“amdyxs yqzsdwq csbfxj”是什么意思? yxs文件用什么打开 请大家用指向函数的指针作函数参数为我举例!谢谢! 声卡怎么下载? 电池不耐用是怎么回事 手机电池太不耐用了? 户籍在河南,学籍在郑州,在哪儿高考呀? 苹果的IOS13.5更新了哪些功能? lol启动不了? 舌苔黄是有啥病 舌苔发黄是什么原因还有异味 舌头发黄是什么症状 宝藏世界下载 为什么我的宝藏世界闪退? 如果电脑版宝藏世界下载之后显示模块失效该怎么办? 什么软件里面买的游戏全,想买游戏宝藏世界 宝藏世界如何切换战斗模式和建造模式 宝藏世界攻略 夏家三千金的主要演员 夏家三千金全集80演员表 夏家三千金叫什么 Y夏家三千金演员表Z 夏家三千金里面都是谁演的,演员里有徐州人?