堆和栈的一些知识

 

堆和栈的一些知识

堆(heap)在空间上手动分配或释放,通过C语言中的mallocC++中的new来完成,分配的空间可以不连续,是一种链式结构;堆有很大的存储空间;

栈(stack)在空间上由操作系统分配或回收;栈的空间有限;程序在编译期间完成对函数和变量在栈上的分配,在运行时对函数的调用传递参数的传递是在栈上完成,且分配一般是连续的,是一种线性结构。

下面通过一段程序,可以看出堆和栈的一些区别:

 

#include <stdio.h>

#include <stdlib.h>

 

int x;       //全局变量,放在静态数据区,连续存放

int y;

int z;

 

int fn(int u,int v,int w/*参数变量及函数返回值放在栈stack,连续*/)

{

 

       int a;                     //函数内部变量放在动态数据区(栈stack)上,连续

       int b;

       int c;

 

       static int l;

       static int m;    //静态全局变量,放在静态数据区,不一定连续

       static int n;

 

 

       char *p = (char *)malloc(4); //分配空间,放在动态数据区(堆heap)上,不连续

       char *q = (char *)malloc(4);

       char *s = (char *)malloc(4);

 

 

       printf("参数变量放在动态数据区(栈stack):/n");

       printf("&u=%08x/n",&u);

       printf("&v=%08x/n",&v);

       printf("&w=%08x/n",&w);

 

       printf("/n/n全局变量放在静态数据区:/n");

       printf("&x=%08x/n",&x);

       printf("&y=%08x/n",&y);

       printf("&z=%08x/n",&z);

 

       printf("/n/n静态全局变量放在静态数据区:/n");

       printf("&l=%08x/n",&l);

       printf("&m=%08x/n",&m);

       printf("&n=%08x/n",&n);

 

 

       printf("/n/n函数内部变量放在动态数据区(栈stack):/n");

       printf("&a=%08x/n",&a);

       printf("&b=%08x/n",&b);

       printf("&c=%08x/n",&c);

 

       printf("/n/n分配空间放在动态数据区(堆heap):/n");

       printf("p=%08x/n",p);

       printf("q=%08x/n",q);

       printf("s=%08x/n",s);

 

       return 1;

}

 

void main()

{

       fn(1,2,3);

}

 

执行结果如下图。

 参数变量放在动态数据区(栈stack):
&u=0013ff28
&v=0013ff2c
&w=0013ff30


全局变量放在静态数据区:
&x=00427c40
&y=00427c44
&z=00427c48


静态全局变量放在静态数据区:
&l=00427c50
&m=00427c3c
&n=00427c4c


函数内部变量放在动态数据区(栈stack):
&a=0013ff1c
&b=0013ff18
&c=0013ff14


分配空间放在动态数据区(堆heap):
p=00033940
q=00033978
s=000339b0

       一个进程的内存空间逻辑分为:代码区、静态数据区及动态数据区。堆栈就放在动态数据区。进程的每个线程均有自己的“栈”,均为本地内部变量互不影响(可以想想同名的全局变量和函数内部变量,是能正确访问的)。

程序执行至:fn(1,2,3)处时的栈顶指针ESP = 0012FF34,进入fn()内部后,栈顶指针ESP = 0012FF24,两者相差16个字节,分别为传递的三个参数和保存的一个函数返回:

       ESP = 0012FF30  ------------> 3        //参数从右向左依次压栈

       ESP = 0012FF2C  ------------>2

       ESP = 0012FF28  ------------> 1

       ESP = 0012FF24  ------------> ret             //函数返回值

fn()函数调用完毕后,栈顶指针ESP = 0012FF28,与进入时的ESP = 0012FF34不等,原因是VC默认通用函数时规则为“__cdecl”(fn()函数不清理堆栈,由被调函数main()去清理,若fn()函数前使用关键字“__stdcall”时,进出函数时的栈顶指针ESP就一致了)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值