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

时间:2010-09-01 06:02:06

标签: windows winapi calling-convention stdcall variadic-functions

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

  

__ inline HRESULT __ stdcall
  StringCchPrintfW(
  STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat, ...
  );

stdcall可以有变量参数吗?

1 个答案:

答案 0 :(得分:6)

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

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

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

  

被叫方清理堆栈,所以   编译器生成 vararg 函数   的 __ CDECL

如果编译以下代码并对函数进行反汇编调用,则可以观察到这一点。

int __stdcall Bar(int a, int b, ...)
{
  return b * a;
}

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