stdcall、cdecl 和pascal简介 .

 这三个参数都是告诉编译器参数的传递约定,参数的传递约定是指参数的传递顺序(从左到右还是从右到左)和由谁来恢复堆栈指针(调用者或者是被调用者),在 Win16下有两种约定: C 和 PASCAL。

    C约定规定参数传递顺序是从右到左,即最右边的参数最先压栈,由调用者恢复堆栈指针。

    PASCAL约定和C约定正好相反,它规定参数是从左向右传递,由被调用者恢复堆栈。

    STDCALL是C约定和PASCAL约定的混合体,它规定参数的传递是从右到左, 恢复堆栈的工作交由被调用者完成。Win32只用STDCALL约定, 但除了一个特例, 即: wsprintf。

    __stdcall 这是一种函数调用方式。 __stdcall方式函数的参数压栈顺序从右到左,是Pascal 缺省调用方式,通常用于win32 API中,自己在退出时清空栈。

    __stdcall将参数压栈是按C语言的顺序(从右到左),但与C语言不同的是它是由被调用者将参数从栈中清除,所以它的编译文件比_cdecl小。

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

    __cdecl是C语言采用的默认调用方法,对于传送参数的内存栈却是由调用者来维护的。实现可变参数的调用只能用该方法。是MFC的缺省调用参数。

    __fastcall方式的函数采用寄存器传递参数,VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。

 

调用约定           压参数入栈顺序     把参数弹出栈者         函数修饰名(Calling convention)
-------------------------------------------------------------------------
__cdecl              右->左                     调用者                          _function   
__fastcall           右->左                     被调用者                       @function@nnn    
__stdcall            右->左                     被调用者                      _function@nnn
__pascal           左->右                      被调用者                      _function@nnn
-------------------------------------------------------------------------

 

以上几个关键词可在“windef.h”头文件中找到:

#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

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

    首先,我们谈一下两者之间的区别:WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除??如果我们的函数使用了__cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。

时间: 2025-01-03 07:34:08

stdcall、cdecl 和pascal简介 .的相关文章

cdecl、pascal、stdcall、fastcall

Directive Parameter order   Clean-up Passes parameters in registers?register   Left-to-right         Routine        Yespascal    Left-to-right           Routine     Nocdecl    Right-to-left             Caller        Nostdcall    Right-to-left        

C/C++函数调用的几种方式总结_C 语言

调用函数时,计算机常用栈来存储传递给函数的参数. 栈是一种先进后出的数据结构,栈有一个存储区.一个栈顶指针.栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶).用户可以在栈顶上方向栈中加入数据,这个操作被称为压栈(Push),压栈以后,栈顶自动变成新加入数据项的位置,栈顶指针也随之修改.用户也可以从堆栈中取走栈顶,称为弹出栈(pop),弹出栈后,栈顶下的一个元素变成栈顶,栈顶指针随之修改.函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据,并进行计算.函数计算结束以

关于函数调用方式__stdcall和__cdecl详解_C 语言

关于函数调用方式__stdcall和__cdecl详解 __stdcall __cdecl 两者的相同点与不同点 实例 __stdcall __stdcall的全称是standard call.是C++的标准调用方式. 函数参数的入栈顺序为从右到左入栈.函数返回时使用retn x指令,其中x为调整堆栈的字节数.这种方式叫做自动清栈.即被调用的函数的参数个数是固定的,调用者必须严格按照定义传递参数,一个不多,一个不少. __cdecl __cdecl的全称是C Declaration,即C语言默认

Win32汇编程序的结构和语法

前言 我们了解了Win32汇编的使用环境,在这一节中我们从一个最简单的Win32汇编程序入手来了解一下Win32汇编程序的基本结构和语法. 一.Win32ASM程序的结构和语法 让我们先来看看一个最简单的Win32汇编程序: .386 .model flat, stdcall option casemap :none ; case sensitiveinclude windows.incinclude kernel32.incincludelib kernel32.lib .dataszCapt

汇编中参数的传递和堆栈修正

在 Win32汇编中,我们经常要和 Api 打交道,另外也会常常使用自己编制的类似于 Api 的带参数的子程序,本文要讲述的是在子程序调用的过程中进行参数传递的概念和分析.一般在程序中,参数的传递是通过堆栈进行的,也就是说,调用者把要传递给子程序(或者被调用者)的参数压入堆栈,子程序在堆栈取出相应的值再使用,比如说,如果你要调用 SubRouting(Var1,Var2,Var3),编译后的最终代码可能是 push Var3push Var2push Var1call SubRoutingadd

深入探讨this指针

深入探讨this指针   为了写这篇文章,准备了好长时间,翻遍了箱底的书籍.但是现在还是不敢放开手来写,战战兢兢.不是担心自己写错,而是唯恐自己错误误导别人.同时也希望这篇文章能给你一点收获.既然是深入探讨this指针,所以建议初学者,最好具有一定编译基础,调试基础.如果大家认为这片文章有不满的地方,就给我发信批评一下,以便及时修正. 关于this指针的描述我们一般从语言层次上讲: this指针作为一个隐含参数传递给非静态成员函数,用以指向该成员函数所属类所定义的对象.当不同的对象调用同一个类的

汇编中参数的传递和堆栈修正【转载】

 在Win32汇编中,我们经常要和Api 打交道,另外也会常常使用自己编制的类似于Api 的带参数的子程序,本文要讲述的是在子程序调用的过程中进行参数传递的概念和分析.一般在程序中,参数的传递是通过堆栈进行的,也就是说,调用者把要传递 给子程序(或者被调用者)的参数压入堆栈,子程序在堆栈取出相应的值再使用,比如说,如果你要调用 SubRouting(Var1,Var2,Var3),编译后的最终代码可能是    push Var3    push Var2    push Var1    call

求教,用delphi 调用 c++ 编写的一卡能读卡函数,出现地址错误

问题描述 求教,用delphi 调用 c++ 编写的一卡能读卡函数,出现地址错误 用delphi,调用一卡通的读卡函数,总是出错,请大家帮我看看吧 C++定义: 原型:ReadUid_cst(int& szCardType ,unsigned char* szData) 输入参数:无 输出参数:szCardType:卡类型,1:13.56,2:2.4 szData:UID 返回值:成功返回1, typedef struct _USERDATA_MM1 { char szName[14]; //姓

winapi-pb 调用自制的dll,pb程序崩溃

问题描述 pb 调用自制的dll,pb程序崩溃 这个是BCB写的一个DLL文件,调用他可以正常执行,执行完了,PB崩溃.我看了写的也是标准的dll.高手给帮忙看看. pb 的声明 function int Encrypt(String Str_dwmc,String Str_mac,String Str_Proname,String Str_outdat,String Str_count,ref String Str_ret) //--------------------------------