函数调用栈空间的分配和释放
来源:互联网 发布:java作用域范围 编辑:程序博客网 时间:2024/05/10 21:13
1 函数执行的时候有自己的临时栈 (c++中函数调用时有两个栈空间,对象的栈空间和函数的栈空间)
2 函数的参数就在临时栈中,如果函数传递实参过去,则用来初始化临时参数变量。
#include <stdio.h>int add(int a,int b){printf("%d,%d\n",a,b);return a+b;}int main(){int (*fun)(int) = (int(*)(int))add;int r = fun(1);printf("%d\n",r);return 0;}
参数是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) {}
来源:http://m.blog.csdn.net/blog/wa8887396/8964712
0 0
- 函数调用栈空间的分配和释放
- 高级编程学习笔记(二) 函数调用栈空间的分配和释放
- 指针分配和释放空间
- 为指针分配和释放空间
- 指针分配和释放空间(转)
- 通过函数调用分配空间
- 字符串数组的空间分配与释放
- U盘未分配空间的释放
- 写出内存分配和释放的函数,并指出区别
- new分配空间之后和delete释放空间之后
- 存储空间的分配和释放
- 函数调用和栈的内存分配过程分析
- 设计内存分配和释放两个函数
- Apache中内存分配子的分配和释放函数分析
- C和C++动态内存的申请与释放思考(动态多维数组空间分配)
- 堆和栈的空间分配
- 二维数组分配,释放空间
- 二维数组分配,释放空间
- bower install js使用bower管理js
- 我的CUDA学习笔记
- 【C语言】将字符串顺序翻转,如: I am a student 转成:student a am I
- concatenate two byte arrays
- C语言实现 编写一个函数,传入a,b两个int类型的变量,返回两个值的最大公约数。
- 函数调用栈空间的分配和释放
- UITableView上拉、下拉原理
- Oracle 中,函数如何返回结果集
- 蓝桥杯:算法训练 2的次幂表示
- ARM-Linux支持并自动挂载U盘
- convert a hexadecimal string to a byte string
- html5
- 坑爹的SIGPIPE
- Ajax 学习初步