Вы, вероятно, знаете прототип функции printf примерно так:
int printf(const char *format, ...);
Более полная версия была бы
int __cdecl printf(const char *format, ...);
__cdecl
определяет «соглашение о вызовах», которое, наряду с другими вещами, описывает, как обрабатываются аргументы. В этом случае это означает, что аргументы помещаются в стек и что стек очищается функцией, выполняющей вызов.
Одной альтернативой _cdecl
является __stdcall
, есть и другие. С __stdcall
соглашение состоит в том, что аргументы помещаются в стек и очищаются вызываемой функцией. Однако, насколько я знаю, функция __stdcall
не может принимать переменное число аргументов. Это имеет смысл, поскольку он не знает, сколько стеков нужно очистить.
Суть и короткость в том, что в случае функций __cdecl
безопасно передавать сколько угодно аргументов, поскольку очистка выполняется в коде, выполняющем вызов. Если вы как-то передадите слишком много аргументов функции __stdcall
, это приведет к повреждению стека. Один из примеров того, где это может произойти, если у вас неправильный прототип.
Более подробную информацию о соглашениях о вызовах можно найти в Википедии здесь .