stdcall和cdecl函数调用约定详解

前言

看了网上各种关于stdcall和cdecl五花八门的解释,看了后让人初学者完全懵逼,甚至怀疑人生。

这里我用通俗易懂的方式,给大家讲解一下原理。

首先理解一个知识点,要知道前人为什么要这样做,而不那样做?优点?

 

stdcall和cdecl

都是函数调用约定之所以有不同的约定是由于历史原因,而且不同的编程语言有不同的调用约定,若要跨语言调用,则必须要了解函数调用约定。

函数调用约定

函数调用约定主要指,参数传递方式(从左到右还是从右到左),栈的清理方式(是由函数本身清理栈,还是由调用者清理栈)。

比如我编译一个程序,调用的一个别人编写库,如果说我们用同一种语言编写的,那么无所谓了,但是当我们使用的语言不一样,那就必须要考虑这个问题了。

stdcall

参数从右往左入栈,由函数自身清理栈。

cdecl

参数是从右往左入栈,由函数调用者清理栈。

我们写程序的时候,从不考虑栈的释放问题,什么临时变量什么的根本不用管,其实是编译器帮我们写了一段代码来处理了而已。从这里可以看出函数调用约定的重要性了,比如我们的一个库,里面的函数是由cdecl约定的(调用者清理栈),而我们的一个程序调用了这个库,使用了stdcall(函数自身清理栈)的调用方式来使用该函数,这个时候编译器不会生成清理栈的代码(编译器认为函数既然是stdcall调用,那么我就不用清理了吧),而函数自身也不清理。这不就出乱子了 么。

这里需要说明一下,为什么Windows下的API函数基本上都是stdcall(即WINAPI宏,函数自身清理栈)呢?而且推荐windows下都使用stdcall,假设我们多次调用了同一个系统API,你说我们是在每一个调用处都加清理栈的代码好,还是只函数自身处理栈就行?答案不是显而易见么,第二种方法可以省去不少空间,这不就是重用的思想么。

有人会问,为什么不统一起来,只用一种方式?那么为什么编程语言不是只有一种?当然,历史遗留问题以及优缺点的问题,没有完美的方法,只有合适的方法,况且还有其他的函数调用约定如__thiscall,__fastcall,__pascal,当然这不是本文的重点。

 

你可能感兴趣的:(windows编程,c++,C语言,stdcall,cdecl)