据我所知,只有caller-clean-stack约定可以使用变量参数 顺便说一句,WinApi StringCchPrintfW就像这样声明了。(我删除了SAL)
__ inline HRESULT __ stdcall
StringCchPrintfW(
STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat, ...
);
stdcall可以有变量参数吗?
答案 0 :(得分:6)
没有。 stdcall调用约定让被调用者清理堆栈。由于被调用者正在清理堆栈,因此无法在编译时知道弹出多少,因此它不能具有可变参数。
为了拥有可变数量的函数参数,您需要使用cdecl,让调用者清理堆栈。这个所有编译器都要确定传递了多少个参数,并且由于调用者正在清理堆栈,它还知道在函数调用返回时弹出堆栈的数量。
在上面提到的情况中,声明函数使用__stdcall
,如前所述,它不支持变量参数。在这种情况下,编译器决定忽略定义的调用约定并恢复为__cdecl
。上面提到的stdcall的描述中提到了这种行为。我引用:
被叫方清理堆栈,所以 编译器生成 vararg 函数 的 __ CDECL 强>
如果编译以下代码并对函数进行反汇编调用,则可以观察到这一点。
int __stdcall Bar(int a, int b, ...)
{
return b * a;
}
生成的代码将被视为__cdecl
。至于原因这是这样定义的,我不知道。