_cdecl 是C Declaration的缩写,表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
_stdcall
是Standard
Call的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的
函数在返回后清除,使用的指令是 retn
X,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的
控制参数的生成,不能多,不能少,否则返回后会出错。
PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。返回时的清栈方式忘记了。。。
_fastcall
是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传
递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。
_thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。
_fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。
C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。
带有可变参数的函数必须且只能使用_cdecl方式,例如下面的函数:
int printf(char * fmtStr, ...);
int scanf(char * fmtStr, ...);
这两个关键字看起来似乎很少和我们打交道,但是看了下面的定义(来自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。
到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcal
分享到:
相关推荐
- **返回值**:与 __cdecl 和 __stdcall 类似,返回值通常存储在 EAX 寄存器中。 - **修饰名格式**:函数名修饰为 `@functionname@number` 形式。 #### 应用场景: - **性能敏感的代码**:当函数调用频繁且对性能有...
本文将详细讲解两种常见的函数调用约定:__stdcall和__cdecl。 首先,__stdcall是C++中的标准调用方式,它的主要特征是参数从右到左入栈,即参数在函数调用时逆序放入堆栈。当函数返回时,使用`retn x`指令来清理...
_stdcall、_cdecl和_fastcall 的区别.zip
本文将深入探讨两种常见的调用约定:`__stdcall` 和 `__cdecl`,这两种约定在C++和Windows API编程中尤其常见。 首先,`__cdecl` 是C Declaration的缩写,它是C语言默认的函数调用约定。在`__cdecl`约定中,参数按...
易语言cdecl回调处理源码,cdecl回调处理,stdcall_to_cdecl,stdcall_to_cdecl_free,回调函数,test,VirtualAlloc,VirtualFree,set_data
__stdcall、__cdecl和__fastcall各有优势和应用场景,选择合适的调用约定对于优化代码性能和提高程序的可维护性至关重要。了解这些调用约定的具体细节有助于开发者更好地理解底层机制,并能够根据项目需求做出最佳...
本文将详细介绍四种常见的函数调用约定:`_cdecl`、`_stdcall`、`_fastcall` 和 `_thiscall`。 ### 1. _cdecl (C Declaration) `_cdecl` 是 C 和 C++ 缺省的调用约定。在此约定下,参数是从右到左压入栈中的,并且...
在上面的代码中,`f_stdcall`和`f_cdeclr`分别代表了使用`__stdcall`和`__cdecl`调用约定的函数。我们可以通过汇编语言的视角来看待这两种调用方式的差异: - 对于`__stdcall`: - 在进入函数之前,首先保存`ebp`...
包含 Java 通过 RXTXComm 读写串口数据需要的动态链接库:SuperComSCL2008.Dll、rxtxSerial.dll、rxtxParallel.dll 和操作 SCL2008 显示屏的动态链接库 SCL_API_stdcall.dll、SCL_API_cdecl.dll
本文将深入探讨三种常见的函数调用约定:`__stdcall`、`__cdecl` 和 `__fastcall`,并对比它们的特点和适用场景。 首先,`__cdecl` 是C语言默认的调用约定,也是大多数编译器默认使用的约定。在`__cdecl`中,函数的...
标题中的“TEST DLL (__stdcall)”指的是一个关于创建和使用使用`__stdcall`调用约定的动态链接库(DLL)的技术主题。在Windows操作系统中,DLL是一种可共享的代码库,程序可以在运行时调用其中的函数来实现特定...
以下是一个详细的步骤,说明如何在Linux环境下创建、操作和加载动态库,特别是针对ARM平台。 首先,你需要确保你的开发环境已经准备就绪,包括C/C++编译器(如GCC)以及必要的交叉编译工具链。对于ARM平台,你需要...
"stdcall介绍" stdcall 调用约定是高级语言中的一种函数调用约定,用于解决函数调用时参数传递问题。...stdcall 调用约定和 cdecl 调用约定都是高级语言中常用的函数调用约定,它们的特点和使用方法都是非常不同的。
C++builder调用VCdll.pdf 本文档详细介绍了C++builder调用VC编写的DLL的过程,并对__cdecl、__fastcall、__stdcall三种调用...同时,我们也可以了解到__cdecl、__fastcall、__stdcall三种调用约定的区别和使用方法。
本文将详细介绍两种常见的函数调用约定:`_stdcall` 和 `_cdecl`,并通过具体的示例代码来帮助读者更好地理解它们的工作原理。 #### 二、_stdcall 调用约定详解 `_stdcall` 是一种广泛应用于Windows API中的函数...
本文将详细介绍两种常见的函数调用约定:stdcall 和 cdecl,并探讨它们之间的差异及其应用场景。 #### 1. 基础概念介绍 - **cdecl (Caller-Destructor)**:此调用约定是C语言和大多数C++函数使用的默认约定。在...
根据给定的文件信息,我们可以深入探讨C/C++中几种主要的函数调用方式:__cdecl、__stdcall和__fastcall,以及C++特有的thiscall。 ### __cdecl `__cdecl`,即“C声明”或“C default”,是C/C++中默认的调用约定...
### MFC中_stdcall调用约定 在C和C++编程中,调用约定(call convention)定义了如何在函数调用期间传递参数、清理栈空间等规则。...通过本文的介绍,希望能帮助读者更好地理解和应用`_stdcall`调用约定。