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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…