stdcall可以有一个变量参数吗?

Ben*_*min 3 windows winapi variadic-functions calling-convention stdcall

据我所知,只有caller-clean-stack约定可以使用变量参数.
顺便说一句,WinApi StringCchPrintfW就是这样声明的.(我删除了SAL)

__inline HRESULT __stdcall StringCchPrintfW
(
STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...
);

stdcall可以有变量参数吗?

lin*_*r27 8

没有.stdcall调用约定让被调用者清理堆栈.由于被调用者正在清理堆栈,因此无法在编译时知道弹出多少,因此它不能具有可变参数.

为了拥有可变数量的函数参数,您需要使用cdecl,它让调用者清理堆栈.这个所有的编译器确定传递了多少个参数,并且由于调用者正在清理堆栈,它还知道在函数调用返回时弹出堆栈的数量.

在上面提到的情况中,声明使用函数__stdcall,如前所述,它不支持变量参数.在这种情况下,编译器决定忽略定义的调用约定并恢复为__cdecl.在上面提到的stdcall的描述中提到了这种行为.我引用:

被调用者清理堆栈,因此编译器生成vararg函数 __cdecl.

如果编译以下代码并对函数进行反汇编调用,则可以观察到这种情况.

int __stdcall Bar(int a, int b, ...)
{
  return b * a;
}
Run Code Online (Sandbox Code Playgroud)

生成的代码将被视为__cdecl.至于这个定义的原因,我不知道.

  • @Benjamin:以printf为例.第一个参数告诉其余参数的类型.随着参数推送R2L,它位于堆栈的顶部,因此`printf`可以使用它来确定其他类型.如果参数推送L2R,则TOS将是推送的*last*参数,可以是int或long或double,或者其他什么,但不会告诉`printf`关于其他参数的任何内容. (4认同)