晃晃悠悠

isrobert

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  12 随笔 :: 0 文章 :: 34 评论 :: 0 Trackbacks
<2007年9月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

留言簿(0)

随笔分类

随笔档案

文章档案

相册

收藏夹

相关链接

搜索

最新评论

阅读排行榜

评论排行榜

调用约定(Calling convention)决定以下内容:函数参数的压栈顺序,由调用者还是被调用者把参数弹出栈,以及产生函数修饰名的方法。
上面这段话摘自
[BlueTopic]的BLOG

采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。__fastcall约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。
(上面这段话摘自CSDN)


可见__cdecl和__stdcal之间的唯一区别在于返回时是由被调用者清理栈,还是由调用用者清理栈.
但是,这两种清理栈的方式,会对有什么影响呢?

很感谢 [jxb_memory] 的回答:
_stdcall与_cdecl两者之间的区别:
      WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除??
      如果我们的函数使用了_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。
      如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。
      那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。
      到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字



posted on 2007-05-10 09:48 isrobert 阅读(2199) 评论(3)  编辑 收藏

评论

# re: (函数)调用约定--- __cdecl和__stdcal 2007-06-01 16:18 zc
如果是c的导出函数,用__stdcall会出错

# re: (函数)调用约定--- __cdecl和__stdcal 2007-09-03 15:58 maggie
vc资料站:http://www.vcmsdn.com/     对学习很有帮助的,可以上去

看看,或加群46138350,里面有高手可以请教的。

# re: (函数)调用约定--- __cdecl和__stdcal 2008-05-27 11:53 健康管理
好东西,收藏了

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]