__stdcall、__cdecl 、CALLBACK 几种函数修饰符
CALLBACK == WINAPI ==__stdcall
实际上就是一种调用模式,就是约定由调用函数来自行解决压栈参数,同 pascal 调用。回调函数只能是类的静态成员函数或是类外定义的全局函数
#define CALLBACK __stdcall #define WINAPI __stdcall #define WINAPIV __cdecl #define APIENTRY WINAPI #define APIPRIVATE __stdcall #define PASCAL __stdcall #define cdecl _cdecl #ifndef CDECL #define CDECL _cdecl #endif
VC中主要有两种函数调用方式:
- 一种是__stdcall;
- 另一种是__cdecl;
- 还有第三种 naked(自己编汇编控制堆栈)。
函数的调用方式有两种:一种是PASCAL调用方式,另一种是C调用方式 。
- 使用PASCAL调用方式,被调函数在返回到调用者之前将参数从栈中删除。
- 使用C调用方式,参数的删除是调用者完成的 。
WinMain函数是由系统调用的,Windows系统规定由系统调用的函数都遵守 PASCAL调用方式 。 但是VC中函数的缺省调用方式是__cdecl,也就是C调用方式 。 在Windows编程中将遇到很多声明修饰符,如CALLBACK,WINAPI,PASCAL这些在 IntelCPU的计算机上都是__stdcall。 几乎我们写的每一个WINDOWS API函数都是__stdcall类型的,为什么? 首先,我们谈一下两者之间的区别:
__cdecl 和 __stdcall 的区别
windows的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要执行清除操作,这里就是问题的关键,如何清除?
如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样就带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。
如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。
那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。
到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字。
CALLBACK 关键字
- CALLBACK函数也称为回调函数,是由你自己来设计,但是供windows调用的。如果你写过SDK程序,就该知道WindowProc函数,它是你自己写的,什么消息怎么处理,但是在程序中你并没有去调用这个函数,因为不需要你自己调用,到了该调用的时候windows自然会去调用。如果你的函数不是回调函数,就不要用CALLBACK或者_cdecl来修饰。
- 如果你写回调函数,而且它的参数所占的字节是不可变的,那么就用CALLBACK(大部分是这种情况),如果参数可能会变,那么就用_cdecl 。
注释:
- 所谓的回调函数,就是说,当某一个事件发生时,系统会根据你给出的函数指针来调用你定义的这个回调函数,这是系统提供的一种和用户通讯的方法。他通过调用用户自定义的函数来给用户提供一个处理消息或事件的机制。
- 回调函数并非Windows特有,只要象C/C++这样支持函数指针的语言都有回调函数的概念,它实际上是向被调用函数传一个你的函数地址,然后被调用函数向通过你传入的函数地址来调用你的函数。比如你做了一个遍历树的函数,但你不知遍历者将对各节点做何种处理时,你就可以在这个遍历函数中加一个函数地址的参数,这样调用者在遍历该树时就可以做各种有意义的工作了:比如打印各节点数据、汇总所有节点之类。
- 回调函数(CallBack Function)在windows编程中用到时,是由windows操作系统直接调用的,一般是在windows编程中的对各种事件的响应。在VC编程中不再采用回调函数了,而是采用了begin_messagemap,end_messagemap,它的作用和windows编程中的回调函数(CallBack Function)是一样的。
- 回调函数(CallBack Function)就是函数指针的调用,看看关于函数指针的用法,了解了函数指针也就了解了CALLBACK。设计一个函数接口的参数是某一函数的指针,在设计的函数中调用该函数指针,那么该指针指向的函数就是callback functioin。回调函数是由你来编写其功能实现,由Windows操作系统调用的函数。
__stdcall、__cdecl 、CALLBACK 几种函数修饰符相关推荐
- 应用函数修饰符@来改变AI Studio的输出信息
简 介: 本文原本是为了能够寻找一种可以将AI Studio程序输出的文本快速传送到Windows的方法,现在使用printt替代原来的print进行相应的程序调试. 关键词: print,print ...
- java函数修饰符_Java 函数 面向对象,修饰符,类,构造方法,this
1.函数 函数就是定义在类中,具有特定功能的一段小程序. 在面向对象编程的语言中,函数也叫方法. 2.函数的格式 修饰符 返回值类型 函数名(参数类型 实际参数,....) { 执行语句; retur ...
- python修饰符作用_python函数修饰符@的使用
python函数修饰符@的作用是为现有函数增加额外的功能,常用于插入日志.性能测试.事务处理等等. 创建函数修饰符的规则: (1)修饰符是一个函数 (2)修饰符取被修饰函数为参数 (3)修饰符返回一个 ...
- Python 字符串常见的语句,和练习题,字符串练习题 Python 切片函数修饰符 #精度和进制Python 字符串一些语句练课件练习题
字符串练习题 Python 切片 函数修饰符 #精度和进制 Python 字符串一些语句练 课件练习题 4,.by 字符串的替换 方法 描述 replac ...
- Python学习笔记11:函数修饰符
Python学习笔记11:函数修饰符 Python有很多有趣的特性,其中函数修饰符就是一个. 我们在之前的那个web应用示例中用过如下写法: @web.route('/log') @符号后边的,就是一 ...
- C#的5种访问修饰符
C#的5种访问修饰符 1.public 公共的 public 允许一个类将其成员变量和成员函数暴露给其他的函数和对象.任何公有成员都可以被外部的类访问. class Person {public st ...
- Tensorflow利用函数修饰符@tf.custom_gradients自定义函数梯度
Tensorflow学习笔记(1) 利用函数修饰符@tf.custom_gradients自定义函数梯度_寂乐居士的博客-CSDN博客_tf.custom_gradient python中的修饰符以及 ...
- python中函数修饰符_python中的函数修饰符
首先,什么是函数修饰符?函数修饰符就是对原有函数做一层包装.比如有以下两个函数: def func1(): print 'I am function func1' def func2(): print ...
- python函数修饰符@的使用
python函数修饰符@的作用是为现有函数增加额外的功能,常用于插入日志.性能测试.事务处理等等. 创建函数修饰符的规则: (1)修饰符是一个函数 (2)修饰符取被修饰函数为参数 (3)修饰符返回一个 ...
最新文章
- npm install 报错 npm ERR! code Z_BUF_ERROR 问题解决
- Bitcoin ABC和区块上限——通过技术实现更大的区块
- 第九课 特殊权限set_uid、stick_bit,软链接,硬链接
- 《Think Python》最新中文版火了,附完整PDF下载!
- python找出只出现一次的数字_Python数组中只出现一次的数字
- 一个典型的加了 SAP 注解的 OData 服务明细分析
- python gui tkinter_python学习之GUI(Tkinter)
- 注意!这些行为均涉嫌科研不端!
- iOS 日志管理异常捕获组件LFLogManager
- struts2随笔(一)Action、struts.xml、Interceptor细节
- c语言 消息框,C# McssageBox:消息框
- [LeetCode] Spiral Matrix II
- strstr区分大小写吗_ONU、机顶盒、路由器,遇到问题你会处理了吗?
- 三星手机怎么看html5,高端手机什么样?看三星S20 FE 5G就知道了
- 何宾 单片机原理及应用_单片机原理及应用课后答案讲解
- 数字电路基础知识(一) 复位设计-同步复位与异步复位
- 考华为认证需要准备什么
- K3CLOUD成本管理参数解释
- 显卡无法为此计算机,如何解决win10系统电脑中无法安装intel显卡驱动的问题
- 【火车头采集】如何采集一个网页的多张图片并且下载