stdcall与 cdecl fastcall,cd和st的区别

  stdcall与 cdecl fastcall,cd和st的区别

  这三个参数是告诉编译器关于参数的传递约定。参数的传递约定指的是参数的传递顺序(从左到右或从右到左)以及谁将恢复堆栈指针(调用者或被调用者)。Win16下有两个约定:C和PASCAL。

  c约定规定参数传递的顺序是从右到左,即最右边的参数最先堆栈,调用者还原堆栈指针。

  PASCAL约定正好和C约定相反,约定参数从左到右传递,被调用者还原堆栈。

  STDCALL是C约定和PASCAL约定的混合,规定参数从右向左传递,恢复堆栈的工作留给被调用者。只使用Win32 STDCALL约定,除了一种特殊情况,即:wsprintf。

  __stdcall这是一种调用函数的方法。__stdcall mode函数的参数从右向左堆叠,这是Pascal默认的调用模式。它通常在win32 API中用于在退出时清除堆栈。

  __stdcall按照C语言的顺序(从右到左)对参数进行堆栈,但与C语言不同的是,从堆栈中清除参数的是被调用者,所以其编译后的文件小于_cdecl。

  __stdcall是Windows API函数中默认的调用约定,也被VB、VFP等采用。

  __cdecl是C语言默认采用的调用方法,但是传递参数的内存栈是由调用者维护的。这个方法是调用变量参数的唯一方法。是MFC的默认调用参数。

  __fastcall函数使用寄存器来传递参数。编译完函数后,VC会在函数名前面加上 @ ,在函数名后面加上 @ 和参数的字节数。

  调用调用约定将参数压入堆栈并将参数弹出堆栈。

  -

  __cdecl左右调用者_函数

  __fastcall左右被调用者@function@nnn

  __stdcall右-左callee _function@nnn

  __pascal左右被调用者_函数@nnn

  -

  上述关键字可以在“windef.h”头文件中找到:

  #定义回调__stdcall

  #定义WINAPI __stdcall

  #定义WINAPIV __cdecl

  #定义APIENTRY WINAPI

  #定义APIPRIVATE __stdcall

  #定义PASCAL __stdcall

  #定义cdecl _cdecl

  # ifndef CDECL #定义CDECL _cdecl

  #endif

  我们编写的几乎每个WINDOWS API函数都是__stdcall类型的。为什么?

  首先说一下两者的区别:WINDOWS在调用函数时需要使用堆栈(一种先进后出的存储结构)。当函数调用完成时,需要清除堆栈。这就是问题的症结所在。怎么清除?如果我们的函数使用__cdecl,那么堆栈清理是由调用者完成的,或者用COM术语来说是由客户完成的。这就带来了一个棘手的问题。不同的编译器生成堆栈的方式不同,那么调用者能正常完成清理吗?答案是否定的,如果使用__stdcall就解决了上述问题,函数自行解决清理工作。所以我们在跨平台调用中都会用到__stdcall(虽然有时候会以WINAPI的形式出现)。那么为什么需要_cdecl呢?当我们遇到fprintf()这样的函数时,它的参数是可变的,长度不定。被调用者无法提前知道参数的长度,事后的清理工作无法正常进行。因此,在这种情况下,我们只能使用_cdecl。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: