浅析栈区和堆区堆栈内存分配配的区别

 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
内存分配中,堆和栈的分配方式区别
下载积分:200
内容提示:内存分配中,堆和栈的分配方式区别
文档格式:PDF|
浏览次数:16|
上传日期: 14:26:26|
文档星级:
该用户还上传了这些文档
内存分配中,堆和栈的分配方式区别
官方公共微信2013年12月 Web 开发大版内专家分月排行榜第三
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。对栈的相关操作详解及堆区、栈区的理解 - 推酷
对栈的相关操作详解及堆区、栈区的理解
栈的定义和分类&
&&& &&& 栈是我们线性结构中的一种常见应用。在函数调用、内存分配等也常常跟栈打交道,栈可以简单的理解为是一种可以实现“先进后出”的存储结构。栈又分为静态栈和动态栈。静态栈以类似于数组方式存放,而动态栈以类似于链表的方式存放。
栈区(Stack)和堆区(heap)
&&&&&&&& 栈区主要用于存放局部变量、定义的形参,在定义时局部变量或形参时由系统自动分配,在函数结束时由系统自动回收存储单元。
&&&&&&&& 堆区主要通过new(常用于C++、Java中),malloc(用于C中)等动态开辟的存储块,函数结束时需要我们通过delete(c++中)、free(c中)手动释放
&举例说明:
void f(int n)
double *q=(double *)malloc(200);
其中的n,m,ch,q由栈区分配(由操作系统帮我们自动分配), 200由堆区分配(需要我们手动开辟一块存储单元)。
栈和堆表示的是分配数据的一种方式。静态的或局部变量它们是以压栈和出栈的方式分配内存的(这个就叫栈区),而动态内存它们是以一种叫堆排序的方式分配的内存(这个叫堆区)。笼统的讲:凡是静态分配的全部在栈里面分配, 凡是动态分配的全部在堆里面分配。
对栈进行操作的思路
&&&&&&&& 先讲下思路:我们知道链表主要通过头指针(指向头结点的地址)来对链表中的其它结点进行操作,而头结点本身并没有实际含义(既没有存放有效节点,也没有存放有效节点的个数),但通过它却可以方便我们对链表进行相关操作,如链表的遍历:
void TraverseList(PNODE pHead)
&PNODE p=pHead-&pN//将头结点的指针域指向首结点(链表的第一个有效结点),并赋给指针变量p,此时p指向首节点的地址
&printf(&遍历整个链表:&);
&while(NULL!=p)//当p指向首节点的地址不为NULL(即链表不为空),循环输入个结点的值
&&//当p指向尾结点的地址时,可输出尾结点的值
&&//但此时尾结点指针域为NULL,将跳出while循环
&&printf(&%d& &,p-&data);
&&p=p-&pN//将p指向下一个结点的地址赋给p指针
&printf(&\n&);
在这个对链表进行遍历的函数中,我们可以看到我们只需要一个头指针,就可以遍历整个链表。
同理,我们可以通过初始化造出一个空栈,产生头结点,进而对栈进行相关操作。
typedef struct Node //定义结点的数据类型
&struct Node *pN//指针域
}NODE,*PNODE;
typedef struct Stack //定义一个Stack结构类型,它含有两个指针成员
&PNODE pT//指向栈顶元素
&PNODE pB//指向栈底元素的下一个没有实际含义的元素
}STACK,*PSTACK;
&&&&&& 1.造空栈
&&&&&&&&&&&& void init(PSTACK pS)
&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&动态产生一个头结点, 并让pTop指向该节点;
&&&&&&&&&&&&&&&&&&& && 让pTop和pBottom都指向头结点&;
&&&&&&&&&&&&&&&&&&&&&&&&再让成员pBottom或pTop所指向头结点的指针域为空
&&&&&&&&&& &&& }
&&&&&&&&&&2.压栈(也叫进栈)
&&&&&&&&& void push(PSTACK pS,int val)
&&&&&&&&& {
&&&&&&&&&&&&&&&&& 创建一个新临时结点;
&&&&&&&&&&&&&&&&& 把val赋给该节点的数据域;
&&&&&&&&&&&&&&&&& 让该新节点的指针域指向栈顶;
&&&&&&&&&&&&&&&&&&最后让该新节点成为新栈顶;&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&& }
&&&&&&&&&& 3.出栈
&&&&&&&&&&& bool pop(PSTACK pS)
&&&&&&&&&&& {
&&&&&&&&&&&&&&&&& 先判断栈是否为空;
&&&&&&&&&&&&&&&&& 临时保存一份栈顶结点;
&&&&&&&&&&&&&&&& 让栈顶指针指向下一个结点的地址;
&&&&&&&&&&&&&&&& 释放预先保存的栈顶结点所占的内存;
&&&&&&&&&&& }
完整实例说明:
#include&stdio.h&
#include&malloc.h&
#include&stdlib.h&
typedef struct Node //定义结点的数据类型
struct Node *pN//指针域
}NODE,*PNODE;
typedef struct Stack
PNODE pT//指向栈顶元素
PNODE pB//指向栈底元素的下一个没有实际含义的元素(头结点)
}STACK,*PSTACK;
void init(PSTACK);//产生一个没有实际含义的头结点,并让pTop和pBottom都指向该头结点
void push(PSTACK,int);//压栈(即进栈)
void traverse(PSTACK);//遍历
bool pop(PSTACK);//出栈
int length(PSTACK);//求栈的长度
bool clear(PSTACK);//清空栈
int main()
STACK S;//STACK等价于struct Stack,为变量S分配内存,其中变量S含两个成员pTop,pBottom
init(&S);//目的是造出一个空栈,产生一个头结点,以便对栈就行操作
push(&S,1);
push(&S,2);
push(&S,3);
traverse(&S);
traverse(&S);
printf(&栈的长度为:%d\n&,length(&S));
clear(&S);
printf(&清空后:&);
traverse(&S);
push(&S,7);
push(&S,5);
push(&S,9);
printf(&进栈后:&);
traverse(&S);
void init(PSTACK pS)//造空栈
pS-&pTop=(PNODE)malloc(sizeof(NODE));//产生头结点,并让pTop指向该头结点
if(NULL==pS-&pTop)
printf(&动态内存分配失败!\n&);
exit(-1);//终止程序
pS-&pBottom=pS-&pT //让pTop和pBottom都指向头结点
pS-&pBottom-&pNext=NULL;
void push(PSTACK pS,int val)
PNODE pNew=(PNODE)malloc(sizeof(NODE));//创建新临时节点
if(NULL==pNew)
printf(&动态内存分配失败!\n&);
exit(-1);//终止程序
pNew-&data=
pNew-&pNext=pS-&pT
pS-&pTop=pN
void traverse(PSTACK pS)
PNODE p=pS-&pT
while(p!=pS-&pBottom)
printf(&%d
&,p-&data);
printf(&\n&);
bool pop(PSTACK pS)
if(pS-&pBottom==pS-&pTop)
printf(&栈为空,无法进行出栈操作!\n&);
PNODE p=pS-&pT
printf(&出栈元素为:%d\n&,p-&data);
pS-&pTop=p-&pN
int length(PSTACK pS)
int len=0;
if(pS-&pBottom==pS-&pTop)
printf(&栈为空! &);
PNODE p=pS-&pT
while(p!=pS-&pBottom)
bool clear(PSTACK pS)
if(pS-&pBottom==pS-&pTop)
printf(&栈为空,清空失败! \n&);
PNODE p=pS-&pTop,q;
while(p!=pS-&pBottom)
pS-&pTop=q;
pS-&pTop=pS-&pB
&&&&&&& 1.free(p); 删除的是p指向的那个结点所占的内存,而不是删除p本身所占的内存;释放结点目的主要是为了防止内存泄露(这不像Java,有垃圾回收机制---由垃圾回收器自动帮你回收)。
&&&&&&&& 2.pBottom始终指向的是栈底元素的下一个没有实际含义的元素(头结点),头结点是我们人为造出来的,并不存放有效数据;添加struct Stack(含两个成员pTop、pBottom)这个结构体的目的主要是为了方便我们对栈进行操作。
&&&&&&& 3.初始化时,让pTop和pBottom都指向头结点的目的:一是让它们初始化时所指向的内存地址相同,在整个程序运行过程中,让pBottom始终指向pTop的初始地址,也就是头结点的地址。这样就可以通过pS-&pBottom==pS-&pTop?是否成立来判断pTop是否指向初始化时原头结点(不存放有效数据的,为方便对栈进行操作的附加结点)的地址,即可以判断栈是否为空,因为如果栈含有有效元素的话,那么pTop必定存放的是新元素的地址。
&&&&&&&&&4.结构体Stack成员pBottom的好处主要有:一是在初始化造空栈时,指向头结点;二是可以在&pS-&pBottom==pS-&pTop成立时判断栈为空。 结构体Stack成员pTop的好处主要有:一是和pBottom一样,在初始化造空栈时,指向头结点;二是通过pTop来对栈中有效元素进行压栈、出栈、遍历等相关操作。
有关对线性结构中的栈操作今天就写到这了,明天开始学习线性结构常见应用中的队列。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致内存分配空间中的堆区和栈区的区别
内存分配空间中的堆区和栈区的区别
在C语言中,内存分配的空间一般分为六个区。常量代码区、数据段区、BSS段、堆空间、栈空间以及内存空间。内存空间是从下向上增长的。
(1)、常量区:用来存放代码和常量
(2)、数据段:用来存放初始化的静态变量和全局变量
(3)、bss段:用来存放未初始化的静态变量和全局变量
(4)、堆空间:动态申请的空间,引用的变量实例化存储的空间
(5)、栈空间:用来存放局部变量,形参之类,未进行实例化的引用申请的变量
(6)、内核空间:用来存放内核代码和环境变量
而C语言中尤其是堆区和栈区的比较繁杂,经常容易混淆,笔者就是属于这种经常被绕的头晕的存在。
从上面可以看出堆区和栈区在内存分配管理中是靠着的,但是两者之间存在有缓存区进行隔开,其实堆区和栈区区别还是比较大的,主要在一下六个方面存在着差异:
()、管理方式不同:栈直接由编译器管理(产生和消除),堆由程序员管理,程序员管理其的产生和消除
()、空间大小不同:栈占用的空间较小,而堆占用的空间较大
()、能否产生碎片不同:栈不会产生碎片,但是堆会产生,会有内存泄露的问题
()、生长方向不同:栈是向下压栈,堆是向上存放数据
()、分配方式不同:栈是在程序员申请之后,由系统分配的没有经过初始化的变量,只有动态分配方式。而堆是由程序员自己实例化,创建的已经过初始化的变量,分配方式类似于链表,动态分配和静态分配都可以
()、分配效率不同:栈是由内存分配的,系统专门为其准备寄存器,同时有专门的出栈和入栈指令,因而效率比较高。而堆空间则是库分配的,可能会存在碎片的原因导致内存不连续,因而效率比较低
重点在于分清平时多说的堆空间和栈空间,而我们平时所说的堆栈指的是栈空间。
我的热门文章
即使是一小步也想与你分享o &nbsp,&nbsp
在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。
本文很详细讲解了堆和栈的理论知识,并结合代码分别解释了 C++ 和 java 中堆和栈的区别。
关于伯乐头条
专注于IT互联网,分享业界最新动态。
新浪微博:
推荐微信号
(加好友请注明来意)
- 好的话题、有启发的回复、值得信赖的圈子
- 分享和发现有价值的内容与观点
- 为IT单身男女服务的征婚传播平台
- 优秀的工具资源导航
- 翻译传播优秀的外文文章
- 国内外的精选博客文章
- UI,网页,交互和用户体验
- 专注iOS技术分享
- 专注Android技术分享
- JavaScript, HTML5, CSS
- 专注Java技术分享
- 专注Python技术分享
& 2017 伯乐在线

我要回帖

更多关于 栈的内存分配 的文章

 

随机推荐