_stdcall,_cdecl区别
(1) _stdcall调用
_stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。
WIN32 Api都采用_stdcall调用方式,这样的宏定义说明了问题:
#define WINAPI _stdcall
按C编译方式,_stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如。
(2) _cdecl调用
_cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式,传送参数的内存栈由调用者维护。_cedcl约定的函数只能被C/C++调用,每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。
由于_cdecl调用方式的参数内存栈由调用者维护,所以变长参数的函数能(也只能)使用这种调用约定。关于C/C++中变长参数(…)的问题,笔者将另文详述。
由于Visual C++默认采用_cdecl 调用方式,所以VC中中调用DLL时,用户应使用_stdcall调用约定。
按C编译方式,_cdecl调用约定仅在输出函数名前面加下划线,形如_functionname。
(3) _fastcall调用
_fastcall调用较快,它通过CPU内部寄存器传递参数。
按C编译方式,_fastcall调用约定在输出函数名前面加“@”符号,后面加“@”符号和参数的字节数,形如@functionname@number。
几乎我们写的每一个WINDOWS API函数都是__stdcall类型的,为什么??
首先,我们谈一下两者之间的区别:
WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数
调用完成后,栈需要清除,这里就是问题的关键,如何清除??
如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲
就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同
,那么调用者能否正常的完成清除工作呢?答案是不能。
如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨
(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。
那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变
的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行
,因此,这种情况我们只能使用_cdecl。
到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字.
_stdcall,_cdecl区别的更多相关文章
- __stdcall,__cdecl,__fastcall,_stdcall,_cdecl,_fastcall 区别简介[转]
今天写线程函数时,发现msdn中对ThreadProc的定义有要求: DWORD WINAPI ThreadProc(LPVOID lpParameter); 不解为什么要用WINAPI宏定义,查 ...
- 转:函数调用的区别:_cdecl以及_stdcall
函数调用的几个概念:_stdcall,_cdecl.... 1._stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈.VC将 ...
- linux内核调试指南
linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 ...
- Linux Kernel - Debug Guide (Linux内核调试指南 )
http://blog.csdn.net/blizmax6/article/details/6747601 linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级 ...
- 调用 Dll 中的函数时,出现栈(STACK)的清除问题 -> 故障模块名称: StackHash_0a9e
在一个名为 test.dll 文件中,有一个 Max() 函数的定义是: #ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) __std ...
- 可变参数以及stdcall
void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2); #define EV_CHECK_FMT(a,b) __attribute__((f ...
- .NET本质论 方法
方法和JIT编译 CLR只执行本机的机器代码.如果一个方法体由CIL组成,那么它就必须在调用之前被转换为本机的机器码(将MSIL编译为本机代码,运行库提供了两种方式.一种就是在安装与部署时的预编译(由 ...
- __stdcall,__cdecl,_cdecl,_stdcall,。__fastcall,_fastcall 区别简介
1. 今天写线程函数时,发现msdn中对ThreadProc的定义有要求:DWORD WINAPI ThreadProc(LPVOID lpParameter); 不解为什么要用WINAPI宏定义,查 ...
- 函数调用的区别:_cdecl以及_stdcall
一.概念1)_stdcall调用 _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作,被调函数自身在返回前清空堆栈. WIN32 Api都采用_ ...
随机推荐
- XRecyclerView Scrapped or attached views may not be recycled
将XRecyclerView布局设置为 android:layout_width="match_parent"android:layout_height="match_p ...
- iOS开发小技巧--相机相册的正确打开方式
iOS相机相册的正确打开方式- UIImagePickerController 通过指定sourceType来实现打开相册还是相机 UIImagePickerControllerSourceTypeP ...
- Docker使用
Docker使用注意 关于网络配置 在使用默认的桥接模式下,容器启动后会被分配一个与docker0在同一网段的地址,在容器内部默认显示为eth0,在宿主机上产生一个临时的vethXXX接口. 端口 ...
- ListView的联动实现
情景: ListView中,如果业务需要在点击position为1的item是,将position=1的itemView背景设置为Green:其他的设置为white 如何实现? 实现方案: 通过onI ...
- Vue.JS 对比其他框架
Angular 选择 Vue 而不选择 Angular,有下面几个原因,当然不是对每个人都适合: 在 API 与设计两方面上 Vue.js 都比 Angular 简单得多,因此你可以快速地掌握它的全部 ...
- Java+jquery实现裁剪图片上传到服务器
大体分两步: 1.利用jquery裁剪图片,把裁剪到的几个点传入后端 2.利用前端传入的几个点,来裁剪图片 首先,用到一个jquery的插件 imgAreaSelect 实例及插件下载地址:http: ...
- <<< ajax在jsp中对于https跨域不能访问
XMLHttpRequest cannot load https://www.emaple.com. No 'Access-Control-Allow-Origin' header is presen ...
- Android开发笔记之《远程控制(MQTT|mosquitto) && (ProtocalBuffer | GRPC)》
Android推送方案分析(MQTT/XMPP/GCM): http://www.open-open.com/lib/view/open1410848945601.htmlMQTT官网: http:/ ...
- .Net 中的反射(反射特性) - Part.3
反射特性(Attribute) 可能很多人还不了解特性,所以我们先了解一下什么是特性.想想看如果有一个消息系统,它存在这样一个方法,用来将一则短消息发送给某人: // title: 标题:author ...
- arguments
arguments 转数组 通常使用下面的方法来将 arguments 转换成数组: Array.prototype.slice.call(arguments); 还有一个更简短的写法: [].sli ...