stdcall and cdecl

Raymond Chen gives a nice overview of what __stdcall and __cdecl does.

(1) The caller “knows” to clean up the stack after calling a function because the compiler knows the calling convention of that function and generates the necessary code.

void __stdcall StdcallFunc() {}

void __cdecl CdeclFunc()
{
    // The compiler knows that StdcallFunc() uses the __stdcall
    // convention at this point, so it generates the proper binary
    // for stack cleanup.
    StdcallFunc();
}

It is possible to mismatch the calling convention, like this:

LRESULT MyWndProc(HWND hwnd, UINT msg,
    WPARAM wParam, LPARAM lParam);
// ...
// Compiler usually complains but there's this cast here...
windowClass.lpfnWndProc = reinterpret_cast<WNDPROC>(&MyWndProc);

So many code samples get this wrong it’s not even funny. It’s supposed to be like this:

// CALLBACK is #define'd as __stdcall
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg
    WPARAM wParam, LPARAM lParam);
// ...
windowClass.lpfnWndProc = &MyWndProc;

However, assuming the programmer doesn’t ignore compiler errors, the compiler will generate the code needed to clean up the stack properly since it’ll know the calling conventions of the functions involved.

(2) Both ways should work. In fact, this happens quite frequently at least in code that interacts with the Windows API, because __cdecl is the default for C and C++ programs according to the Visual C++ compiler and the WinAPI functions use the __stdcall convention.

(3) There should be no real performance difference between the two.

Leave a Comment