W CDECL argumenty są umieszczane na stosie w odwrotnej kolejności, wywołujący czyści stos, a wynik jest zwracany przez rejestr procesora (później będę nazywać go „rejestrem A”). W STDCALL jest jedna różnica, dzwoniący nie wyczyścił stosu, a calle to zrobił.
Pytasz, który jest szybszy. Nikt. Powinieneś używać rodzimej konwencji wywoływania tak długo, jak możesz. Konwencję należy zmieniać tylko wtedy, gdy nie ma wyjścia, podczas korzystania z bibliotek zewnętrznych, które wymagają użycia określonej konwencji.
Poza tym istnieją inne konwencje, które kompilator może wybrać jako domyślną, np. Kompilator Visual C ++ wykorzystuje FASTCALL, który teoretycznie jest szybszy z powodu szerszego wykorzystania rejestrów procesora.
Zwykle musisz nadać prawidłową sygnaturę konwencji wywoływania funkcjom zwrotnym przekazanym do jakiejś zewnętrznej biblioteki tj. qsort
Wywołanie zwrotne do z biblioteki C musi być CDECL (jeśli kompilator domyślnie używa innej konwencji to musimy oznaczyć wywołanie zwrotne jako CDECL) lub różne wywołania zwrotne WinAPI muszą być STDCALL (całe WinAPI to STDCALL).
Innym typowym przypadkiem może być przechowywanie wskaźników do niektórych funkcji zewnętrznych, tj. Aby utworzyć wskaźnik do funkcji WinAPI, jej definicja typu musi być oznaczona STDCALL.
A poniżej przykład pokazujący, jak robi to kompilator:
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)