В CDECL аргументы помещаются в стек в обратном порядке, вызывающий очищает стек, и результат возвращается через реестр процессора (позже я назову его «регистром A»). В STDCALL есть одно отличие: вызывающий объект не очищает стек, а вызываемый объект.
Вы спрашиваете, какой из них быстрее. Ни один. Никто. Вы должны использовать собственное соглашение о вызовах как можно дольше. Изменяйте соглашение только в том случае, если выхода нет, при использовании внешних библиотек, требующих использования определенного соглашения.
Кроме того, существуют другие соглашения, которые компилятор может выбрать по умолчанию, например, компилятор Visual C ++ использует FASTCALL, который теоретически быстрее из-за более широкого использования регистров процессора.
Обычно вы должны указать правильную подпись соглашения о вызовах для функций обратного вызова, переданных в некоторую внешнюю библиотеку, то есть обратный вызов qsort
из библиотеки C должен быть CDECL (если компилятор по умолчанию использует другое соглашение, мы должны пометить обратный вызов как CDECL) или различные обратные вызовы WinAPI должны быть STDCALL (весь WinAPI - STDCALL).
Другой обычный случай может быть, когда вы сохраняете указатели на некоторые внешние функции, т.е. чтобы создать указатель на функцию WinAPI, определение ее типа должно быть помечено с помощью STDCALL.
А ниже - пример, показывающий, как это делает компилятор:
i = Function(x, y, z);
int Function(int a, int b, int c) { return a + b + c; }
CDECL:
push on the stack a copy of 'z', then a copy of 'y', then a copy of 'x'
call (jump to function body, after function is finished it will jump back here, the address where to jump back is in registers)
move contents of register A to 'i' variable
pop all from the stack that we have pushed (copy of x, y and z)
copy 'a' (from stack) to register A
copy 'b' (from stack) to register B
add A and B, store result in A
copy 'c' (from stack) to register B
add A and B, store result in A
jump back to caller code (a, b and c still on the stack, the result is in register A)
STDCALL:
push on the stack a copy of 'z', then a copy of 'y', then a copy of 'x'
call
move contents of register A to 'i' variable
pop 'a' from stack to register A
pop 'b' from stack to register B
add A and B, store result in A
pop 'c' from stack to register B
add A and B, store result in A
jump back to caller code (a, b and c are no more on the stack, result in register A)