__cdecl和__stdcall区别

__cdecl和__stdcall的调用约定不同.

调用约定(Calling convention)决定以下内容:函数参数的压栈顺序,由调用者还是被调用者把参数弹出栈,以及产生函数修饰名的方法.

1)采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈.因此,实现可变参数的函数只能使用该调用约定.由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大.

2)采用__stdcall约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定.由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈.

     

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

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

你可能感兴趣的:(Windows)