1

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

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

Может ли stdcall иметь переменные аргументы?

ответ

5

stdcall Конвенция о созыве призвания очищает стек. Поскольку вызывающая сторона очищает стек, нет возможности узнать во время компиляции, сколько выскочить, поэтому он не может иметь переменные аргументы.

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

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

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

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

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

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

+0

http://en.wikipedia.org/wiki/X86_calling_conventions#stdcall – Benjamin

+0

Да, извините. Смутился со старым соглашением о вызове 'pascal'. – linuxuser27

+0

Не быть. Спасибо :) – Benjamin

Смежные вопросы