Может ли stdcall иметь переменные аргументы?
Насколько я знаю, только соглашение о чистом стеке вызывающей стороны может использовать переменные аргументы.
Кстати, WinApi StringCchPrintfW объявлен так (я удалил SAL)
__inline HRESULT __stdcall
StringCchPrintfW (
STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, ...
);
Может ли stdcall иметь переменные аргументы?
1 ответ
Нет. Соглашение о вызовах stdcall позволяет вызываемому объекту очистить стек. Поскольку вызываемый объект очищает стек, у него нет возможности узнать во время компиляции, сколько нужно вытолкнуть, поэтому он не может иметь переменные аргументы.
Чтобы иметь переменное число аргументов функции, вам нужно использовать cdecl, который заставляет вызывающую программу очищать стек. Это все, что нужно компилятору для определения количества передаваемых аргументов, и, поскольку вызывающая сторона очищает стек, она также знает, сколько нужно вытолкнуть из стека при возврате вызова функции.
В случае, упомянутом выше, функция объявлена для использования __stdcall
, который, как упоминалось ранее, не поддерживает переменные аргументы. В этом случае компилятор принимает решение проигнорировать определенное соглашение о вызовах и вернуться к __cdecl
, Это поведение упоминается в описании для stdcall, упомянутом выше. Я цитирую:
Вызываемый объект очищает стек, поэтому компилятор выполняет функции vararg __cdecl.
Это можно наблюдать, если следующий код скомпилирован, а вызов функции разобран.
int __stdcall Bar(int a, int b, ...)
{
return b * a;
}
Полученный код будет рассматриваться как __cdecl
, Что касается причины, по которой это определено, я не знаю.