Может ли stdcall иметь переменные аргументы? - PullRequest
1 голос
/ 01 сентября 2010

Насколько я знаю, только соглашение о чистом стеке вызывающей стороны может использовать переменные аргументы.
Кстати, WinApi StringCchPrintfW объявлен так. (Я удалил SAL)

__inline HRESULT __stdcall
StringCchPrintfW (
STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, ...
4 *

1012 * 4);* Может ли stdcall иметь переменные аргументы?

1 Ответ

6 голосов
/ 01 сентября 2010

Нет. Соглашение о вызовах stdcall позволяет вызываемому объекту очистить стек. Поскольку вызываемый объект очищает стек, у него нет возможности узнать во время компиляции, сколько нужно извлечь, поэтому он не может иметь переменные аргументы.

Чтобы иметь переменное число аргументов функции, вам нужно использовать cdecl , который заставляет вызывающую программу очищать стек. Это все, что нужно компилятору для определения количества передаваемых аргументов, и, поскольку вызывающая сторона очищает стек, она также знает, сколько нужно вытолкнуть из стека при возврате вызова функции.

В вышеупомянутом случае объявляется, что функция использует __stdcall, которая, как упоминалось ранее, не поддерживает переменные аргументы. В этом случае компилятор принимает решение игнорировать определенное соглашение о вызовах и возвращается к __cdecl. Это поведение упоминается в описании для stdcall , упомянутом выше. Я цитирую:

Вызываемый очищает стек, поэтому компилятор выполняет функции vararg __ Cdecl .

Это можно наблюдать, если следующий код скомпилирован, а вызов функции разобран.

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

Полученный код будет обрабатываться как __cdecl. Что касается причины , это определено таким образом, я не знаю.

...