高级编程学习笔记(二) 函数调用栈空间的分配和释放

原地址:http://blog.csdn.net/a8887396/article/details/8964712


1 函数执行的时候有自己的临时栈 (c++中函数调用时有两个栈空间,对象的栈空间和函数的栈空间)


 2 函数的参数就在临时栈中,如果函数传递实参过去,则用来初始化临时参数变量。


[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int add(int a,int b)  
  4. {  
  5.     printf("%d,%d\n",a,b);  
  6.     return a+b;  
  7. }  
  8.   
  9. int main()  
  10. {  
  11.     int (*fun)(int) = (int(*)(int))add;  
  12.     int r = fun(1);  
  13.     printf("%d\n",r);  
  14.     return 0;  
  15. }  


参数是fun传递的,实际调用的函数是add,在调用函数初始化临时变量时,如果栈中有传参数,则初始化临时变量,若没有,则不初始化。
所以上文中会出现一个很大的值,因为b没有被初始化
但如果 
int (*fun)(int) = (int(*)(int))add; 改成 int (*fun)(int,int,int) = (int(*)(int,int,int ))add;
int r = fun(1); 改成 int r = fun(1,2,5); 
这时的返回值是正确的(3),因为add中的2个临时变量都被初始化来,并且add中没有第三个参数,所以5不会被使用.也不会出问题



3 返回值的返回形式
  通过寄存器返回值 (通过返回值返回值)

 通过参数返回值 (存放返回值的参数必须是指针,指针指向的区域必须事先分配)

 如果通过参数返回指针,那么参数就必须是双指针 (以此类推,参数是三指针,是向通过参数返回双指针)


4 调用约定
__stdcall
__cdecl
__fastcall
  调用约定(Calling convention)决定以下内容: 函数参数的压栈顺序,由调用者还是被调用者把参数弹出栈,以及产生函数修饰名的方法。
  采用__cdecl约定时:函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。
  采用__stdcal约定时:函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。
  采用__fastcall约定时:将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的堆栈。__fastcall约定一般指传送不超过4个字节的参数,通过寄存器,不用栈,这样比较快。
  __cdecl和__stdcal之间的唯一区别在于返回时是由被调用者清理栈,还是由调用用者清理栈。
  但是,这两种清理栈的方式,会对有什么影响呢?
  __stdcall与__cdecl两者之间的区别:
  WINDOWS的函数调用时需要用到栈(STACK,一种先入后出的存储结构)。当函数调用完成后,栈需要清除,这里就是问题的关键,如何清除?
  如果函数使用_cdecl,那么栈的清除工作是由调用者,用COM的术语来讲就是客户来完成的。这样带来了一个棘手的问题,不同的编译器产生栈的方式不尽相同,那么调用者能否正常的完成清除工作呢?答案是不能。
  如果使用__stdcall,上面的问题就解决了,函数自己解决清除工作。所以,在跨(开发)平台的调用中,我们都使用__stdcall(虽然有时是以WINAPI的样子出现)。
  那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用_cdecl。
  到这里我们有一个结论,如果你的程序中没有涉及可变参数,最好使用__stdcall关键字。


语法格式

linux下
int __attribute__((stdcall)) add(int *a,int *b){}
windows下
int  __stdcall add(int *a,int *b) {}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值