stdcall和cdecl [英] stdcall and cdecl
问题描述
有两种类型的调用约定:stdcall和cdecl。我有几个问题。
- 当调用者调用cdecl函数时,调用者
如何知道是否应释放堆栈?在调用站点,
调用者是否知道被调用的函数是cdecl还是stdcall
函数?它是如何工作的 ?调用者如何知道是否应该
释放堆栈? - 如果一个被声明为stdcall的函数调用一个函数(
有一个调用约定为cdecl),或者反过来,
这不恰当吗? - 一般来说,我们可以说哪个调用会更快 - cdecl或
stdcall? - When a cdecl function is called by the caller, how does a caller know if it should free up the stack ? At the call site, does the caller know if the function being called is a cdecl or a stdcall function ? How does it work ? How does the caller know if it should free up the stack or not ? Or is it the linkers responsibility ?
- If a function which is declared as stdcall calls a function(which has a calling convention as cdecl), or the other way round, would this be inappropriate ?
- In general, can we say that which call will be faster - cdecl or stdcall ?
Raymond Chen对 (1)调用者在调用函数之后知道清理堆栈,因为编译器知道该函数的调用约定并生成必要的代码。 可能不匹配的调用约定,像这样: 很多代码示例得到这个错误,甚至不是很有趣。它应该是这样的: (2)两种方法都应该工作。实际上,这至少在与Windows API交互的代码中频繁发生,因为 (3)两者之间应该没有真正的性能差异。 There are two types of calling conventions - stdcall and cdecl. I have few questions on them.
Raymond Chen gives a nice overview of what (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. It is possible to mismatch the calling convention, like this: So many code samples get this wrong it's not even funny. It's supposed to be like this: 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 (3) There should be no real performance difference between the two. 这篇关于stdcall和cdecl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! __ stdcall
和 __ cdecl
做了一个很好的概述。 p>
void __stdcall StdcallFunc(){}
void __cdecl CdeclFunc()
{
/ /编译器知道StdcallFunc()在此时使用__stdcall
//约定,因此它为堆栈清理生成适当的二进制
//。
StdcallFunc();
}
LRESULT MyWndProc(HWND hwnd,UINT msg,
WPARAM wParam,LPARAM lParam);
// ...
//编译器通常抱怨,但是有这里转换...
windowClass.lpfnWndProc = reinterpret_cast< WNDPROC>(& MyWndProc);
// CALLBACK是#define'd作为__stdcall
LRESULT CALLBACK MyWndProc hwnd,UINT msg
WPARAM wParam,LPARAM lParam);
// ...
windowClass.lpfnWndProc =& MyWndProc;然而,假设程序员不忽略编译器错误,编译器将生成需要清除的代码(例如:
<因为它会知道涉及的函数的调用约定。
__ cdecl
是根据Visual C ++编译器的C和C ++程序的默认值和 WinAPI函数使用 __ stdcall
约定。
__stdcall
and __cdecl
does.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();
}
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);
// CALLBACK is #define'd as __stdcall
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg
WPARAM wParam, LPARAM lParam);
// ...
windowClass.lpfnWndProc = &MyWndProc;
__cdecl
is the default for C and C++ programs according to the Visual C++ compiler and the WinAPI functions use the __stdcall
convention.