__stdcall和__cdecl
最近学习回调函数
在回调函数前都要加__stdcall 说是参数入栈方式不同,以及释放方式不同,找了半天也只找到一些汇编的文章,本人汇编不太好 也看不太明白是什么意思
向各位过来的大侠请教下
1.为什么回调一定要加__stdcall,回调不是动态绑定函数(通过函数指针绑定)但加__stdcall是为什么啊
2.一般函数函数是__cdecl,他和__stdcall到底有什么不同,哪位能不能给个简单的代码函数,调用后可以直观的看到结果的不同
以上请各位指教,谢谢!
[解决办法]
调用前后对比@esp的值,__stdcall是被调用者恢复栈,__cdecl是调用者.
[解决办法]
回调不一定必须stdcall,只是在windows api中调用api和回调都使用stdcall
两种call的主要不同在谁负责恢复堆栈上
[解决办法]
如果仅仅在c语言层面上几乎看不出他们的不同
[解决办法]
因为微软开发 Windows 时就是这么用的,所以你凡是涉及到传递给 Windows API 的函数地址,都必须是按照微软的规定来。虽然微软的函数已经编译为 dll 成品,但其内部用的是 __stdcall,虽然回调函数也是你写的,但是传递给它调用,两者必须统一。但如果你自己写函数来调用,怎么写都是没关系的。就如 4 楼所说,在 C 语言里你看不出区别的。
[解决办法]
cdecl是调用者恢复堆栈的,假设有一百个不同的函数调用函数a
那么内存中就有一百端恢复堆栈的代码,是不是很浪费空间呢?
stdcall是函数恢复堆栈,只有在函数代码的结尾出现一次恢复堆栈的代码,所以节约空间
注意,这些恢复堆栈的代码是编译器根据你给他的call方式自动生成的,所以你无需考虑…而告诉编译器call方式的意义就在这里,如果一方用cdecl一方用stdcall可能出现没有人释放堆栈的情况,这明显是不允许的
[解决办法]
cdecl的优势在于他可以不定参数个数,参考printf函数
原因在于是调用者存入参数,调用者释放参数占有的空间,都是调用者完成的,所以有参数个数的自由性
stdcall在结束函数时,回复的空间是编译时决定的,函数负责释放,但他无法知道你实际压入几个参数,于是stdcall在编译时就规定了参数个数,无法实现不定个数的参数调用
话说有好奇心是好事呀~