3

私の知る限り、可変引数を使用できるのは caller-clean-stack 規則だけです。
ちなみに、WinApi StringCchPrintfW はこのように宣言されています。 (SAL は削除しました)

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

stdcall にも可変引数を指定できますか?

4

1 に答える 1

8

いいえ。stdcall呼び出し規約では、呼び出し先がスタックをクリーンアップします。呼び出し先はスタックをクリーンアップしているため、コンパイル時にポップオフする量を知る方法がないため、可変引数を持つことはできません。

可変数の関数引数を使用するには、 cdeclを使用する必要があります。これにより、呼び出し元がスタックをクリーンアップします。これはすべて、渡された引数の数を決定するためのすべてのコンパイラであり、呼び出し元がスタックをクリーンアップしているため、関数の呼び出しが返されたときにスタックからポップする量も知っています。

上記の場合、関数は use と宣言されていますが__stdcall、これは前述のように可変引数をサポートしていません。この場合、コンパイラは、定義された呼び出し規約を無視して に戻す決定を下し__cdeclます。この動作は、上記のstdcallの説明で言及されています。私は引用します:

呼び出し先がスタックを消去するため、コンパイラはvararg関数 __cdeclを作成します。

これは、次のコードがコンパイルされ、関数の呼び出しが逆アセンブルされた場合に確認できます。

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

結果のコードは として扱われ__cdeclます。これがそのように定義されている理由については、私にはわかりません。

于 2010-09-01T06:03:51.143 に答える