__cdecl
__cdecl
是 C 和 C++ 程序的默认调用约定。 由于堆栈已由调用方清理,因此它可以执行 vararg
函数。 __cdecl
调用约定创建的可执行文件大于 __stdcall 调用约定创建的可执行文件,这是因为它要求每个函数调用包括堆栈清理代码。 以下列表显示此调用约定的实现。 __cdecl
修饰符是 Microsoft 专用的。
元素 | 实现 |
---|---|
参数传递顺序 | 从右到左。 |
堆栈维护职责 | 调用函数从堆栈中弹出自变量。 |
名称修饰约定 | 下划线字符 (_) 作为名称的前缀,导出使用 C 链接的 __cdecl 函数时除外。 |
大小写转换约定 | 不执行任何大小写转换。 |
注意
有关信息,请参阅修饰名。
将 __cdecl
修饰符放置在变量或者函数名称的前面。 由于 C 命名和调用约定为默认值,因此你只能在指定 /Gv
(vectorcall)、/Gz
(stdcall) 或 /Gr
(fastcall) 编译器选项时,在 x86 代码中使用 __cdecl
。 /Gd 编译器选项强制执行 __cdecl
调用约定。
在 ARM 和 x64 处理器上,接受 __cdecl
,但编译器一般会忽略它。 按照 ARM 和 x64 上的约定,自变量将尽可能传入寄存器,后续自变量传递到堆栈中。 在 x64 代码中,使用 __cdecl
可重写 /Gv 编译器选项并使用默认 x64 调用约定。
对于非静态类函数,如果函数是超行定义的,则调用约定修饰符不必在超行定义中指定。 也就是说,对于类非静态成员方法,在定义时假定声明期间指定的调用约定。 给定此类定义:
struct CMyClass {
void __cdecl mymethod();
};
此:
void CMyClass::mymethod() { return; }
等效于此:
void __cdecl CMyClass::mymethod() { return; }
为了与以前的版本兼容,cdecl 和 _cdecl 是 __cdecl
的同义词,除非指定了编译器选项 /Za(禁用语言扩展)。
示例
在下面的示例中,将指示编译器对 system
函数使用 C 命名和调用约定。
// Example of the __cdecl keyword on function
int __cdecl system(const char *);
// Example of the __cdecl keyword on function pointer
typedef BOOL (__cdecl *funcname_ptr)(void * arg1, const char * arg2, DWORD flags, ...);