What are the key factors on using different calling conventions? When does someone know to use specific calling conventions such as __cdecl
or __stdcall
or __fastcall
in different occasions.
Examples would be really apprciated.
What are the key factors on using different calling conventions? When does someone know to use specific calling conventions such as __cdecl
or __stdcall
or __fastcall
in different occasions.
Examples would be really apprciated.
Most of the time you don't need to worry about it. Usually you'll use __cdecl
, but only because that's the default in Visual C++. C++ member functions, however, use the __thiscall
convention by default in Visual C++
A (rather common) situation where you really have to worry about calling conventions is when you pass callbacks to API functions, like those in the Windows API:
// CALLBACK is #define'd as __stdcall
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg
WPARAM wParam, LPARAM lParam);
// ...
windowClass.lpfnWndProc = &MyWndProc;
::RegisterClass(&windowClass);
Here, we declare MyWndProc()
as having the __stdcall
convention (CALLBACK
is #define
'd as __stdcall
). This is needed because the operating system expects that lpfnWndProc
points to a WNDPROC
, which uses the CALLBACK
convention.
Just about every Windows API function that accepts a callback requires the callback functions to use the __stdcall
convention, and since __cdecl
is usually the default, you must make this explicit (you would use CALLBACK
for window procedures).
This is extremely important because stack corruption can occur if the operating system attempts to call a non-__stdcall
function. Unfortunately enough people get this wrong that Windows will actually check for calling convention mismatch specifically for window procedures.
While __stdcall
is required for callback functions passed to WinAPI functions, functions that accept a variable number of arguments must use the __cdecl
calling convention, because only the caller will know how to properly pop the variable number of arguments off the stack. Since __cdecl
is usually the default, you don't need to explicitly specify __cdecl
for functions that accept a variable number of arguments.
I personally haven't found a use for __fastcall
, although I'm sure someone has.
__clrcall
is relevant only if you're interacting with managed code.