__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, ...);

另请参阅

自变量传递和命名约定
关键字