当前位置:文档之家› 一文让你彻底明白“应用工程的堆与栈”

一文让你彻底明白“应用工程的堆与栈”

一文让你彻底明白“应用工程的堆与栈”
一文让你彻底明白“应用工程的堆与栈”

应用工程的堆与栈

一、基本知识

C语言因其高效率而成为目前嵌入式微控制器(MCU)编程中使用最多的编程语言,堆栈是C语言区别于汇编语言的最大特点,也是其高效运行的基础。1、定义

1)基本含义

事实上,堆栈包括堆(heap)和栈(s tack)两个不同的概念,只是因为其二者都占用MCU的片上RAM空间并对系统内存进行分配和管理,而被习惯性放在一起说。

在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。

可以理解成堆栈是位于MCU片上RAM空间上的一个特殊存储区。

小注:

?堆:队列优先,先进先出(FIFO—first in first out)

?栈,先进后出(FILO—First-In/Last-Out)。

2)详解介绍

①堆(heap)是用于动态分配内存的RAM区域,heap的空间是用户手动申请和释放的:C语言中的malloc(size),calloc(num,size)函数分配heap,释放使用free(*heap)函数;

②栈(stack)用于分配函数临时变量、在函数调用或中断产生时保存内核CPU 运行时上下文(run time context—包括内核CPU通用寄存器、SP和PC寄存器、状态寄存器(如S12内核的CCR寄存器,存放内核CPU的计算状态)及函数当前的临时变量)以及函数参数传递;其占用的RAM大小与CPU架构(不同的内核CPU其位宽和CPU寄存器数量各不相同)和编译器采用的嵌入式应用程序二进制接口(Embedded Application Binary Interface)有关。

小注:

?栈(Stack)是CPU根据程序运行需求自动分配(也叫push,即压栈)和释放

(也称作pop,即出栈)的,无需用户自己维护,但需要在C工程的链接文件

中指定其大小。

?压栈(push):函数调用和中断ISR运行之前,对当前运行函数运行时的上下

文进行保护。

?出栈(pop):函数返回和中断返回时恢复调用函数和中断发生前函数的运行

时环境。

?栈可以由高地址向低地址生长,也可以由低地址向高地址生长,具体与CPU

架构有关,以下为S12内核CPU异常/中断产生时的压栈情况:

2、片内RAM段划分

嵌入式MCU的片内RAM一般会被链接文件“分区”为如下几个段(section):1).bss:未初始化段

MCU启动(boot/startup)过程中会将该RAM区初始化为0;

2).data:数据段

该RAM区存放初始化值不为0的全局变量,其初始化值放置在编译结果

的.copy(Flash/EEPROM)数据区,每次MCU启动时,会将其初始值取出对.data 区进行初始化;

3).heap:堆段

该地址空间的大小在C工程的链接文件中给出,CPU会自动保留该区域,并初始化用于堆管理的指针链表。因为嵌入式MCU的片上RAM资源都非常小,是十分宝贵的资源,而使用heap对RAM空间进行动态管理效率极低,所以在嵌入式编程中极少使用heap,默认的嵌入式MCU C语言应用工程中是没有.heap段的;

4).stack:栈段

该地址空间的大小在C工程的链接文件中给出,CPU会自动保留该区域,不对其进行任何初始化,但在进入C语言main () 函数之前必须将.stack的起始地址(stack的最小地址或最高地址,也称为栈顶—stack top,具体取决于该CPU 架构的栈生长方式)赋值给CPU的栈指针寄存器SP(stack pointer),该过程也被称为堆栈初始化;

常见的嵌入式C语言应用工程各数据段、代码段和堆栈的分配如下图所示:

2、片内Flash/EEPROM段划分

放在Flash/EEPROM等NVM(Non-VolatileMemory—非易失性存储器)中的默认段包括:

1).text: 代码段

用于存放C应用工程中所有C函数代码的编译结果,比如启动函startup,main函数等;

2).copy:拷贝段

用于存放.data段的初始化值;

3).const:常量段

用于存放工程中使用const修饰定义或者#define定义的常量;

4)interrupt vector table:中断向量表

用于存放包含默认复位向量在内的内核CPU异常和外设中断向量表,其为内核CPU异常或者外设中断的中断服务函数ISR地址数组;

二、应用工程栈大小的确定

由上述stack的用途可知,一个嵌入式C语言应用工程所需的栈大小与其函数调用层数以及是否有中断嵌套密切相关。

函数调用层级越多,中断嵌套越多,函数局部变量越多,函数的形参越多其stack消耗也就越多。

1、栈的内存分配

嵌入式MCU软件开发集成环境(IDE)中的链接器(linker)会根据工程的链接文件(linkerfile)分配stack大小的地址范围,在工程编译生成的map(内存映射)文件中能够看到stack占用具体RAM地址范围;当然在map文件中一般也可以看到工程中各函数的调用关系,从而可以分析出工程的最大函数调用层级,然后debug工程。

在该最大调用函数中设置一个断点,观察CPU的SP寄存器值,用该值与栈顶相减即可得到该工程函数调用所需的最大stack空间,在该值的基础上考虑中断嵌套,再增加相应的中断嵌套所需的stack消耗,即可估计出整个工程运行时所需的stack大小。

如果某个函数中使用了大量的局部变量,那可能包含该函数的调用嵌套才是整个工程的“关键路径”,而非真实调用层级最多但不包含该函数的”关键路径”,一般建议再增加一定字节的stack作为系统裕量。

2、map文件的划分

以下为基于一个S12XEP100的实际CodeWarrior5.1 IDE工程map文件的分析:

三、堆栈溢出定义、危害以及应对措施

1、定义

基于以上对栈的分析,可知

堆栈溢出是指随着程序的运行,栈的使用超出了工程配置时在链接文件中给其分配的空间大小,而内核CPU又未对其进行检查和限制,从而使用相邻的其他RAM段(比如全局变量所在.data段或者.bss段),从而导致的栈修改全局变量或者全局变量修改栈内容的问题。

2、危害

由于堆栈上保存了内核CPU运行的关键数据,所以其溢出的危害十分严重,具体如下:

1)栈数据覆盖全局变量:

全局变量意外修改

①被修改全局变量为程序if,while,for,switch语句判断条件,导致程序运

行出错,功能异常;

②被修改全局变量为指针地址或数组索引变量,非法操作/修改系统数据,比

如外设配置寄存器,导致外设工作异常;

对全局变量的修改改变了栈上的数据

①影响栈上保存的调用函数/中断发生前函数的局部变量,数据意外修改,函

数运行异常,功能异常;

②影响栈上保存的函数返回地址(PC寄存器),返回到不确定的地址运行,

导致功能异常甚至死机非法地址复位等;

③影响栈上保存的原函数堆栈指针(SP寄存器),返回后数据(局部变量和全

局变量)操作异常,导致功能失效;

④影响栈上保存的调用函数运行时的内核CPU状态(CCR寄存器),函数判断

语句运行错误(数学逻辑计算结果—N/Z/V/C-bit)、全局中断意外禁止/打开

(I-bit)、低功耗进入意外允许/禁止(S-bit),导致程序跑飞、程序锁死、无法进入低功耗等;

2)基于以上分析,建议在开发嵌入式应用工程代码时遵循以下规则以防止堆栈溢出:

函数参数最好不要超过3个,如果要传递更多的参数,请使用全局变量、指针、数据或结构体;

不要定义过大的局部变量,建议最好保证每个函数的局部变量不大于10个字节,若大于10个字节,尽量使用全局变量;

慎用递归函数;

外设中断嵌套不宜过多,能不用最好不用,要用最多运行3级中断优先级嵌套,并在估计工程stack使用量时将最大嵌套可能性考虑在内;

使用数据指针修改内存时,必须相对其赋值,且不能指向stack区,否则可以造成stack意外修改(保存在stack上的函数返回地址,CPU运行状态CCR寄存器或者影响函数运行的局部变量),从而导致程序跑飞;

若使用了uCOS-III或者FreeRTOS等时时操作系统,使能其内核的堆栈溢出检查功能钩子函数(hook function);下图为MPC5748G SDK(S32DSfor Power V1.2 IDE)中提供的FreeRTOS配置:

如果条件允许,购买使用专业的代码运行时分析工具,比如IAR的C-STAT等对应用工程进行分析评估;

计算机算法设计与分析习题和答案解析

《计算机算法设计与分析》习题及答案 一.选择题 1、二分搜索算法是利用(A )实现的算法。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 2、下列不是动态规划算法基本步骤的是(A )。 A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解 3、最大效益优先是( A )的一搜索方式。 A、分支界限法 B、动态规划法 C、贪心法 D、回溯法 4. 回溯法解旅行售货员问题时的解空间树是( A )。 A、子集树 B、排列树 C、深度优先生成树 D、广度优先生成树 5.下列算法中通常以自底向上的方式求解最优解的是( B )。 A、备忘录法 B、动态规划法 C、贪心法 D、回溯法 6、衡量一个算法好坏的标准是(C )。 A 运行速度快 B 占用空间少 C 时间复杂度低 D 代码短 7、以下不可以使用分治法求解的是(D )。 A 棋盘覆盖问题 B 选择问题 C 归并排序 D 0/1背包问题 8. 实现循环赛日程表利用的算法是( A )。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 9.下面不是分支界限法搜索方式的是( D )。 A、广度优先 B、最小耗费优先 C、最大效益优先 D、深度优先 10.下列算法中通常以深度优先方式系统搜索问题解的是( D )。 A、备忘录法 B、动态规划法 C、贪心法 D、回溯法 11.备忘录方法是那种算法的变形。(B ) A、分治法 B、动态规划法 C、贪心法 D、回溯法 12.哈夫曼编码的贪心算法所需的计算时间为( B )。 A、O(n2n) B、O(nlogn) C、O(2n) D、O(n) 13.分支限界法解最大团问题时,活结点表的组织形式是( B )。 A、最小堆 B、最大堆 C、栈 D、数组 14.最长公共子序列算法利用的算法是( B )。 A、分支界限法 B、动态规划法 C、贪心法 D、回溯法 15.实现棋盘覆盖算法利用的算法是( A )。 A、分治法 B、动态规划法 C、贪心法 D、回溯法 16.下面是贪心算法的基本要素的是( C )。 A、重叠子问题 B、构造最优解 C、贪心选择性质 D、定义最优解 17.回溯法的效率不依赖于下列哪些因素( D ) A.满足显约束的值的个数 B. 计算约束函数的时间 C.计算限界函数的时间 D. 确定解空间的时间 18.下面哪种函数是回溯法中为避免无效搜索采取的策略( B ) A.递归函数 B.剪枝函数C。随机数函数 D.搜索函数 19. ( D )是贪心算法与动态规划算法的共同点。

堆与栈

栈是由编译器在需要的时分配的,不需要时自动清除的变量存储区。里面的变量通常是局部变量、函数参数等。堆是有malloc()函数(C++语言为new运算符)分配为内存快,内存的释放由程序员手动控制,在C语言为free()完成(C++中为deleted)。堆和栈的主要区别有以下几点: (1)管理方式不同 栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。 (2)空间的大小不同 栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先设定好,当申请的空间超过栈的剩余空间时,将提示溢出。因此,用户能从栈获得空间较小。 堆是向高地址扩展的数据结构,是不连续的内存区域。因为系统是用链表来存储空闲内存地址的,且链表的遍历方向是由低地址向高地址。由此可见,堆获得空间较灵活,也较大。栈中元素都是一一对应的,不会存在一个内存块从中弹出的情况。 (3)是否产生碎片 对于栈来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。 (4) 增长方向不同 堆的增长方向是向上的,即向着内存地址增加的方向。栈的增长方向是向下的,即向着内存地址减小的方向。 (5)分配方式不同 堆都是程序中由malloc()函数动态申请分配并由free()函数释放的;栈的分配和释放是由编译器完成的,栈的动态分配由alloca()函数完成,但是栈的动态分配和对不同,它的动态分配是由编译器进行申请和释放的,无需手工实现。 (6)分配效率不同 栈是由机器系统提供的数据结构,计算机会在底层对栈提供支持;分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令进行。堆则是C函数库提供的,它的机制很复杂,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大的空间,如果没有足够大的空间(可能是由于内存碎片太多),就需要操作系统来重新整理内存空间,这样就有机会分到足够大小的内存,然后返回。 显然堆的效率要比栈低得多。 可执行代码运行时内存结构结构: (1)代码区(text segment)。代码区指令根据程序设计流程依次执行,对于顺序指令,则只会执行一次(每个进程),如果反复,则需要使用跳转指令,如果进行递归,则需要借助栈来实现。 代码区的指令包括操作码和要操作的对象(或对象地址引用)。如果是里技术(及具体的数值),将直接包含在代码中;如果是局部变量,将在栈区分配空间。然后引用该数的地址;如果是BSS去和数据区,在代码中同样是引用该数的地址。

堆 栈 详 解

堆栈详解及其python实现 wiki定义 堆栈(抽象数据类型) 有关在会计中使用术语LIFO,请参阅LIFO(会计)。对于力量训练中使用术语下推,请参阅下推(练习)。 有关其他用途,请参阅堆栈(消歧)。 使用推送和弹出操作简单表示堆栈运行时。 在计算机科学中,堆栈是一种抽象数据类型,用作元素集合,具有两个主要操作: push,它为集合添加了一个元素,以及 pop,删除最近添加的尚未删除的元素。 元素从堆栈中出现的顺序产生了它的替代名称LIFO(last in,first out)。另外,窥视操作可以在不修改堆栈的情况下访问顶部。[1]这种结构的名称“堆叠”来自于相互堆叠的一组物理项目的类比,这样可以轻松地将物品从堆叠顶部取出,同时获取物品堆叠深度可能需要先取下多个其他物品。[2] 被认为是线性数据结构,或者更抽象地是顺序集合,推送和弹出操作仅发生在结构的一端,称为堆栈的顶部。这使得可以将堆栈实现为单链表和指向顶部元素的指针。可以实现堆栈以具有有界容量。如果堆栈已满并且没有足够的空间来接受要推送的实体,则认为堆栈处于溢出状态。pop 操作从堆栈顶部删除一个项目。

需要堆栈来实现深度优先搜索。 非必要的操作 软件堆栈 堆栈和编程语言 硬件堆栈 堆栈的基本架构 堆叠在主内存中 堆叠在寄存器或专用存储器中 堆栈的应用 表达式评估和语法分析 编译时间内存管理 高效的算法 也可以看看 进一步阅读 另见:Jan?ukasiewicz§工作 Stacks于1946年进入计算机科学文献,当时Alan M. Turing使用术语“埋葬”和“unbury”作为从子程序调用和返回的手段。[3]子程序已于1945年在Konrad Zuse的Z4中实施。 克劳斯·萨梅尔森和弗里德里希·L·包尔的慕尼黑工业大学提出这个构想于1955年并于1957年申请了专利,[4]和1988年3月鲍尔收到的计算机先驱奖为堆原理发明。[5]同样的概念是由澳大利亚人Charles Leonard Hamblin在1954年上半年独立开发的。[6]

C语言堆和栈

在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到。 但对于很多的初学着来说,堆栈是一个很模糊的概念。堆栈:一种数据结构、一个在程序运 行时用于存放的地方,这可能是很多初学者的认识,因为我曾经就是这么想的和汇编语言中 的堆栈一词混为一谈。我身边的一些编程的朋友以及在网上看帖遇到的朋友中有好多也说不 清堆栈,所以我想有必要给大家分享一下我对堆栈的看法,有说的不对的地方请朋友们不吝 赐教,这对于大家学习会有很大帮助。 首先在数据结构上要知道堆栈,尽管我们这么称呼它,但实际上堆栈是两种数据结构:堆和栈。 堆和栈都是一种数据项按序排列的数据结构。 我们先从大家比较熟悉的栈说起吧,它是一种具有后进先出性质的数据结构,也就是说 后存放的先取,先存放的后取。这就如同我们要取出放在箱子里面底下的东西(放入的比较 早的物体),我们首先要移开压在它上面的物体(放入的比较晚的物体)。而堆就不同了,堆 是一种经过排序的树形数据结构,每个结点都有一个值。通常我们所说的堆的数据结构,是 指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。由于 堆的这个特性,常用来实现优先队列,堆的存取是随意,这就如同我们在图书馆的书架上取 书,虽然书的摆放是有顺序的,但是我们想取任意一本时不必像栈一样,先取出前面所有的 书,书架这种机制不同于箱子,我们可以直接取出我们想要的书。 然而我要说的重点并不在这,我要说的堆和栈并不是数据结构的堆和栈,之所以要说数 据结构的堆和栈是为了和后面我要说的堆区和栈区区别开来,请大家一定要注意。 下面就说说C语言程序内存分配中的堆和栈,这里有必要把内存分配也提一下,大家不 要嫌我啰嗦,一般情况下程序存放在Rom或Flash中,运行时需要拷到内存中执行,内存会分 别存储不同的信息,如下图所示:

计算机组成原理堆栈

堆栈是计算机系统中的一个重要概念,也是理解微型计算机组成的一个基础概念。堆栈是一种存储部件,即数据的写入跟读出不需要提供地址,而是根据写入的顺序决定读出的顺序。 堆栈也是一种数据结构。有一个地址指针总指向最后一个压入堆栈的数据所在的数据单元,存放这个地址指针的寄存器就叫做堆栈指示器。数据一个一个地存入,这个过程叫做“压栈”。在压栈的过程中,每有一个数据压入堆栈,就放在和前一个单元相连的后面一个单元中,堆栈指示器中的地址自动加1。读取这些数据时,按照堆栈指示器中的地址读取数据,堆栈指示器中的地址数自动减1。这个过程叫做“出栈pop”。如此就实现了后进先出的原则。 一般的堆栈存储器由RAM、寄存器A,寄存器B构成。算术运算一般在寄存器A和寄存器B 之间进行,其中的数据可能来自于进栈的输入也可能来自栈堆的出栈。运算结果则会放入寄存器B中以待下步操作。 此次的课程设计做出的堆栈处理器,使其能与外部数据总线进行数据交换,且符合堆栈要求(先进后出),并能对存储的数据进行算术运算,且存储的数据的数据位不少于8位,通过数码管显示操作数据及运算结果(只有寄存器A、B 直接与外部总线进行数据交换,RAM只和寄存器B进行数据交换)。 关键词:堆栈,RAM, PUSH, POP , 寄存器A,寄存器B

一. 任务解析 (3) 二. 系统方案论证 (3) 2.1总体方案与比较论证 (3) 2.2 设计思路 (4) 2.3系统原理与结构 (4) 2.3.1 系统框图 (4) 2.3.2 系统结构框图 (5) 2.3.3堆栈电路图 (5) 三. 设计过程 (6) 3.1堆栈存储器的设计 (6) 3.1.1堆栈存储器设计原理及仿真结果 (6) 3.2对数据进行算术运算的设计及仿真 (7) 3.2.1 对存储器中数据进行加法运算 (7) 3.2.2 对存储器中数据进行减法运算 (8) 3.2.3 对存储器中数据进行乘法运算 (8) 3.2.4 对存储器中数据进行除法运算 (9) 四. 总结 (9) 4.1遇到的问题及解决方案 (9) 4.2设计心得 (10) 4.3参考文献 (10)

物质的微观构成和宏观组成(1)

1、分子和原子: 2、分子是由原子构成的;有些分子由同种原子构成如:1个氧分子(O 2)是由 多数分子由不同种原子构成如:1个二氧化碳分子(CO 2)是由 3、注意:水是由水 构成的, 水分子是由 构成的, 1个水分子是由 和 构成的。 有的物质是由原子直接构成的,如:汞是由 4、用分子观点解释由分子构成的物质的物理变化和化学变化 物理变化: 。 化学变化: 。 如:水蒸发时水分子的 变大,但水分子 ,故为 变化, 实验室用过氧化氢分解制取氧气时, 分子就变成了 和 ,故为 变化。 再如,加热红色的氧化汞粉末时, 会分解成 和 ,每 个 结合成 个 ,许多 聚集成 。 5、化学变化的实质:在化学变化过程中, 分裂变成 , 重新组合,形成新物质 的 。如:水在化学变化中的最小粒子是 。 6、从微观角度解释纯净物和混合物(由分子构成的物质)的区别: 纯净物 ,混合物由 如: 又如图: 7、原子的构成 (1)原子结构示意图的认识 8、原子是由居于原子中心的 和原子核是由 和 两种粒子构成的。 9、由于原子核内的质子带__________________,中子____________,原子核带的___________________与____________________相等, 相反,所以整个原子不显电性。 不同种类的原子,核内的质子数________,核外的电子数______________。 10、在原子中 =______________=________________ 11、不同原子的根本区别是__________________________________ 说明:原子一般是由质子、中子和电子构成,有的原子不一定有中子,质子数也不一定等于中子数。

堆栈及静态数据区详解

堆、栈及静态数据区详解 五大内存分区 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。 自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free 来结束自己的生命的。 全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多) 明确区分堆与栈 在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。 首先,我们举一个例子: void f() { int* p=new int[5]; } 这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下: 00401028 push 14h 0040102A call operator new (00401060) 0040102F add esp,4 00401032 mov dword ptr [ebp-8],eax 00401035 mov eax,dword ptr [ebp-8]

java中堆和栈的区别

Java中堆与栈的区别 简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存。 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java 自动管理栈和堆,程序员不能直接地设置栈或堆。 2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。 3. Java中的数据类型有两种。 一种是基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出

堆变量和栈变量

全局,静态,new产生的变量都在堆中 动态分配的变量在堆中分配 局部变量在栈里分配 函数中声明的变量在栈中 用了new标示符在堆中 全局变量和static变量都在全局区 程序为栈变量分配动态内存,在程序结束时为栈变量分配的空间将自动释放;而为堆变量分配的空间则不会自动释放,若在程序中没有没有释放堆变量,它将一直占用系统内存。 堆栈是一种执行“后进先出”算法的数据结构。 设想有一个直径不大、一端开口一端封闭的竹筒。有若干个写有编号的小球,小球的直径比竹筒的直径略小。现在把不同编号的小球放到竹筒里面,可以发现一种规律:先放进去的小球只能后拿出来,反之,后放进去的小球能够先拿出来。所以“先进后出”就是这种结构的特点。 堆栈就是这样一种数据结构。它是在内存中开辟一个存储区域,数据一个一个顺序地存入(也就是“压入——push”)这个区域之中。有一个地址指针总指向最后一个压入堆栈的数据所在的数据单元,存放这个地址指针的寄存器就叫做堆栈指示器。开始放入数据的单元叫做“栈底”。数据一个一个地存入,这个过程叫做“压栈”。在压栈的过程中,每有一个数据压入堆栈,就放在和前一个单元相连的后面一个单元中,堆栈指示器中的地址自动加1。读取这些数据时,按照堆栈指示器中的地址读取数据,堆栈指示器中的地址数自动减 1。这个过程叫做“弹出pop”。如此就实现了后进先出的原则。 堆栈是计算机中最常用的一种数据结构,比如函数的调用在计算机中是用堆栈实现的。 堆栈可以用数组存储,也可以用以后会介绍的链表存储。 下面是一个堆栈的结构体定义,包括一个栈顶指针,一个数据项数组。栈顶指针最开始指向-1,然后存入数据时,栈顶指针加1,取出数据后,栈顶指针减1。 #define MAX_SIZE 100 typedef int DATA_TYPE; struct stack { DATA_TYPE data[MAX_SIZE]; int top; }; 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程

堆栈详解(数据与内存中的存储方式)

堆栈详解(数据与内存中的存储方式) char* r = "hello word!";char b[]="hello word!"*r = 'w';*b='w';其实应该是语法错误,可是VC++6.0没有警告或者错误,r指向的是文字常量区,此区域是编译的时候确定的,并且程序结束的时候自动释放的,*r = 'w';企图修改文字常量区引起错误,b的区别在于其空间是在栈上分配的,因此没有错误。const char* r = "hello word!";*r = 'w';一个由 c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束后有系统释放4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放5、程序代码区—存放函数体的二进制代码。二、例子程序//main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main(){int b; 栈char s[] = "abc"; 栈char *p2; 栈char *p3 = "123456"; 123456\0在常量区,p3

在栈上。static int c =0;全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20);分配得来得10和20字节的区域就在堆区。strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。}二、堆和栈的理论知识2.1申请方式stack:由系统自动分配。例如,声明在函数中一个局部变量int b; 系统自动在栈中为b开辟空间heap:需要程序员自己申请,并指明大小,在c中malloc函数如p1 = (char *)malloc(10);在C++中用new运算符如p2 = (char *)malloc(10);但是注意p1、p2本身是在栈中的。 2.2申请后系统的响应栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。2.3申请大小的限制栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的

堆与栈,静态变量和全局变量的区别

堆与栈,静态变量和全局变量的区别 堆与栈,静态变量和全局变量的区别 对和栈的主要的区别由以下几点: 1、管理方式不同; 2、空间大小不同; 3、能否产生碎片不同; 4、生长方向不同; 5、分配方式不同; 6、分配效率不同; 管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。 空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改: 打开工程,依次操作菜单如下:Project->Setting->Link,在Category 中选中Output,然后在Reserve中设定堆栈的最大值和commit。 注意:reserve最小值为4Byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。 生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。 分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

一文解析STM32内存管理和堆栈的认知与理解

一文解析STM32内存管理和堆栈的认知与理解 本文主要介绍了STM32内存管理和堆栈的认知与理解,首先介绍的是内存管理的实现原理及分配、释放原理,其次介绍了stm32的存储器结构,最后阐述了堆栈的认知与理解,具体的跟随小编一起来了解一下吧。 STM32内存管理详解内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存管理的实现方法有很多种,他们其实最终都是要实现2 个函数:malloc 和free;malloc 函数用于内存申请,free 函数用于内存释放。 内存管理的实现原理 从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为n 块,对应的内存管理表,大小也为n,内存管理表的每一个项对应内存池的一块内存。内存管理表的项值代表的意义为:当该项值为0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为10,那么说明包括本项对应的内存块在内,总共分配了10 个内存块给外部的某个指针。内寸分配方向如图所示 到低位地址)即首先从最末端开始找空内存。当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。 分配原理 当指针p 调用malloc 申请内存的时候,先判断p 要分配的内存块数(m),然后从第n 项开始,向下查找,直到找到m 块连续的空内存块(即对应内存管理表项为0),然后将这m 个内存管理表项的值都设置为m(标记被占用),最后,把最后的这个空内存块的地址返回指针p,完成一次分配。注意,如果当内存不够的时候(找到最后也没找到连续的m 块空闲内存),则返回NULL 给p,表示分配失败。 释放原理

氢元素

氢(Hydrogen) 氢是一种化学元素,化学符号为H,原子序数为1,在元素周期表中位于第一位。它的原子是所有原子中最小的。氢通常的单质形态是氢气。它是无色无味无臭,极易燃烧的由双原子分子组成的气体,氢气是最轻的气体。 简介 氢(qīng;Hydrogen) 氢是一种化学元素,化学符号为H,原子序数是1,在元素周期表中位于第一位。它的原子是所有原子中最小的。 氢通常的单质形态是氢气。它是无色无味无臭,极易燃烧的由双原子分子组成的气体,氢气是最轻的气体。它是宇宙中含量最高的物质。氢原子存在于水所有有机化合物和活生物中。导热能力特别强,跟氧化合成水。在0℃和一个大气压下,每升氢气只有0.09克——仅相当于同体积空气质量的14.5分之一(实际比空气轻14.38倍)。元素在太阳中的含量:(%) 75;地壳中含量:1.5 % 在常温下,氢气比较不活泼,但可用催化剂活化。单个存在的氢原子则有极强的还原性。在高温下氢非常活泼。除稀有气体元素外,几乎所有的元素都能与氢生成化合物。 氢结构示意图氢内部示意图 名称、符号、序号:氢、H、1 氢气的化学式:H2 系列:非金属 族周期, 元素分区:1族1, s 颜色和外表:无色 声音在其中的传播速率(m/s):1310 大气含量:0.0001 % 地壳含量:0.88 % 原子属性 原子量:1.00794 原子量单位氧化价(氧化物):1(两性的)晶体结构:六角形 物质属性 物质状态气态 核内质子数:1 核外电子数:1 核电荷数:1 质子质量:1.673E-27 质子相对质量:1.008 所属周期:1 所属族数:IA 摩尔质量:1g/mol 氢化物:无 氧化物:H2O 最高价氧化物:H2O 颜色和状态:无色气体 原子半径:0.79 常见化合价:+1,-1 熔点:14.025 K (-259.125 °C)沸点:20.268 K (-252.882 °C)声速:1270 m/s(293.15K)

关于堆栈的讲解(我见过的最经典的

一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束后有系统释放 4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放 5、程序代码区—存放函数体的二进制代码。 二、例子程序 这是一个前辈写的,非常详细 //main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char *p2; 栈 char *p3 = "123456"; 123456\0在常量区,p3在栈上。 static int c =0;全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来得10和20字节的区域就在堆区。 strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 } 二、堆和栈的理论知识 2.1申请方式 stack: 由系统自动分配。例如,声明在函数中一个局部变量int b; 系统自动在栈中为b开辟空间heap: 需要程序员自己申请,并指明大小,在c中malloc函数 如p1 = (char *)malloc(10); 在C++中用new运算符 如p2 = (char *)malloc(10); 但是注意p1、p2本身是在栈中的。

详解堆栈的几种实现方法

详解堆栈的几种实现方法 基本的抽象数据类型(ADT)是编写C程序必要的过程,这类ADT有链表、堆栈、队列和树等,本文主要讲解下堆栈的几种实现方法以及他们的优缺点。 堆栈(stack)的显著特点是后进先出(Last-In First-Out, LIFO),其实现的方法有三种可选方案:静态数组、动态分配的数组、动态分配的链式结构。 静态数组:特点是要求结构的长度固定,而且长度在编译时候就得确定。其优点是结构简单,实现起来方便而不容易出错。而缺点就是不够灵活以及固定长度不容易控制,适用于知道明确长度的场合。 动态数组:特点是长度可以在运行时候才确定以及可以更改原来数组的长度。优点是灵活,缺点是由此会增加程序的复杂性。 链式结构:特点是无长度上线,需要的时候再申请分配内存空间,可最大程度上实现灵活性。缺点是链式结构的链接字段需要消耗一定的内存,在链式结构中访问一个特定元素的效率不如数组。 首先先确定一个堆栈接口的头文件,里面包含了各个方案下的函数原型,放在一起是为了实现程序的模块化以及便于修改。然后再接着分别介绍各个方案的具体实施方法。 堆栈接口stack.h文件代码: [cpp] view plain copy 1 /*** 堆栈模块的接口 stack.h #include #define STACK_TYPE int /* 堆栈所存储的值的数据类型 */ /*** 函数原型:create_stack ** 创建堆栈,参数指定堆栈可以保存多少个元素。 ** 注意:此函数只适用于动态分配数组形式的堆栈。*/ void create_stack(size_t size);

1已知氢元素有3种同位素氧元素也有3种同位素

1已知氢元素有3种同位素氧元素也有3种同位素.假定能准确测定单个水分子的质量则所测得数据将有种[ ]A6种 B7种 C18种D27种 2.某元素原子的最外层电子数与次外层电子数相同,且最外层电子数与次外层电子数之和小于8,它是[ ]A.锂 B.铍 C.氦 D.钙3.非金属元素R其质量数为127,又知R离子含有74个中子,54个电子,则该元素最高化合价组成的化合物是[ ] A.R(OH)3 B.R2O7 C.HRO3 D.H2R 4.下列各组微粒具有相同质子数和电子数的是A.CH4,NH3,H2O,ArB.OH-,NH4+,H3O+,NeC.H3O+,NH4+,Na+,HFDOH-,F-,Mg2+,Na + 5.下列叙述中正确的是[ ]A.40K和40Ca原子中的质子数和中子数都不相等B.金刚石和石墨的性质相同C.H2和D2互为同位素D.某物质中只含一种元素,该物质一定是纯净物 6.某化合物由A,B 2种元素组成,已知A,B两元素的质量比为7∶4,相对原子质量之比为7∶8,则此化合物分子式可能是[ ]A.A2B B.AB C.AB2 D.A2B4 7.氧化性由弱到强,原子或离子半径由大到小的一组微粒是[ ]A.O,Cl,S,P B.K+,Al3+,Ca2+,Ba2+ C.Rb,K,Na,Li D.K+,Mg2+,Al3+,H+ 8.下列各项描述中,正确的是[ ] A.某元素原子最外层只有一个电子,则它一定是ⅠA元素B.任何原子或离子的组成中都含有质子C.质子数相同的微粒一定属于同种元素D.构成原子核的微粒中都含有中子 9.目前含有元素硒(Se)的保健品已开始涌入市场,已知它与氧同主族,而与钙同周期,下列关于硒的有关描述中不正确的是[ ]A.原子序数为24 B.最高价氧化物为SeO3,为酸性氧化物C.原子半径比钙小D.气态氢化物分子式为H2Se,性质不稳定 10.关于化学键的各种叙述中,下列说法中正确的是[ ]A.在离子晶体里,只存在离子键B.共价化合物里,一定不存在离子键C.非极性键只存在于双原子的单质分子里D.由不同元素组成的多原子分子里,一定只存在极性键 11.第3周期元素R,它的原子核外层上达到饱和所需电子数小于次外层和最内层电子数之差,且等于最内层电子数的正整数倍.则关于R的正确说法是[ ]A.常温下,能稳定存在的R的高价氧化物都能与烧碱溶液反应B.R的最高价氧化物对应水化物是强酸C.R和R的氧化物的熔点和硬度都很高D.R能形成稳定的气态氢化物 12.下列关于元素化合价的叙述中,错误的是[ ]A.ⅢA族的B和Al都能形成+3价的化合物B.ⅤA族的N和P都能形成-3价的化合物C.ⅠA族的Na和K都能形成+1价的化合物D.ⅦA族的F和Cl都能形成+7价的化合物 17.短周期元素X和Y中,X原子的最外层电子数是内层电子总数的一半,Y元素在X元素的前一周期,Y2-离子和Ne原子的电子层结构相同,关于X和Y形成的化合物Z的说法正确的是[]A.Z是一种酸酐 B.Z是一种碱性氧化物C.Z的分子式是X2Y5 D.Z是一种离子晶体 18.元素X的原子获得3个电子或元素Y的原子失去2个电子后,其离子的电子层结构与氖原子的电子层结构相同,X,Y2种元素的单质在高温下得到的化合物的正确的分子式是[ ]A.Y3X2B.X2Y3 C.X3Y2 D.Y2X3 19.同主族元素所形成的同一类型的化合物,其结构和性质往往相似,化合物PH4I是一种无色晶体,下列对它的描述中不正确的是[ ]A.在加热时此化合物可以分解B.它是一种离子化合物C.这种化合物不能跟强碱发生化学反应D.该化合物在一定条件下由PH3与HI化合而成20.有主族元素A、B,A的原子序数为n,A2+离子比B2-离子少8个电子,则B的原子序数是[ ]A.n+4 B.n+6 C.n +8 D.n+10 21R元素原子的质量数为A,Rn+核外电子数为X,则WgRn+离子所含中子数为[ ]22.某元素由2种同位素组成,其原子比为5∶2,第一种同位素的二价阳离子有27个电子,34个中子;第二种同位素原子的中子数比第一种多2个,该元素的平均近似相对原子质量为[ ]A.59.57 B.61.57 C.63.57 D.64.5 23.砷为第四周期ⅤA族元素,根据它在周期表中的位置推测,砷不可能具有的性质是[ ]A.砷在通常状况下为固体B.可以有-3,+3,+5等多种化合价C.As2O5对应水化物的酸性比H3PO4弱D.砷单质的还原性比磷单质的还原性弱24.下列物质按沸点降低顺序排列的一组是[ ]A.Cl4,CBr4,CCl4,CF4 B.O2,S,Se,TeC.HF,HCl,HBr,HI D.F2,Cl2,Br2,I2*26.元素周期表里金属元素和非金属元素分界线附近能找到[ ]A.新制农药元素 B.制催化剂元素C.制半导体元素D.制耐高温合金元素27.与OH-具有相同电子数和质子数的是[ ]A.NH3 B.Na+C.F- D.NH4+28.高温超导体中铊(Tl)是有效成分之一,已知铊是铝的同族元素,关于铊的性质判断可能错误的是[ ]A.铊是银白色质软的金属B.铊能形成+3价的化合物C.Tl(OH)3与Al(OH)3一样,具有两性D.铊可以与稀硝酸反应生成硝酸盐29.某主族元素R原子的质量数为79,已知R离子含有45个中子和36个电子,下列关于R元素的叙述错误的是[ ]A.R元素属于ⅡA族B.R元素在周期表里处于第4周期C.R元素最高氧化物对应水化物的分子式为H2RO4D.R元素气态氢化物的分子式为H2R30.下列关于稀有气体的描述不正确的是[ ]①原子的最外层都有8个电子;②其原子与同周期ⅠA,ⅡA族阳离子具有相同的核外电子排布;③有些稀有气体能跟某些物质反应;④原子半径比同周期ⅦA族元素原子的大.A.① B.①和③ C.①和② D.②和④31.按C,N,O,F的顺序,下列递变规律正确的是]A.原子半径逐渐增大 B.非金属性逐渐减弱C.气态氢化物的稳定性逐渐增强D.单质的氧化性逐渐减弱32.有aX n+和bY n-2种元素的简单离子,若它们的电子层结构相同,则下列关系正确的是[ ] Ab-a=n+m B.a-b=n+mC.离子半径Y m-<X n+ D.原子序数Y>X

C++中堆和栈的区别

C++中堆和栈的区别,自由存储区、全局/静态存储区和常量存储区 文章来自一个论坛里的回帖,哪个论坛记不得了! 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。 自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。 全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的(初始化的全局变量和静态变量在一块区域,未初始化的全局变量与静态变量在相邻的另一块区域,同时未被初始化的对象存储区可以通过void*来访问和操纵,程序结束后由系统自行释放),在C++里面没有这个区分了,他们共同占用同一块内存区。 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多) 明确区分堆与栈 在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。 首先,我们举一个例子: void f() { int* p=new int[5]; } 这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在VC6下的汇编代码如下: 00401028 push 14h 0040102A call operator new (00401060) 0040102F add esp,4 00401032 mov dword ptr [ebp-8],eax 00401035 mov eax,dword ptr [ebp-8] 00401038 mov dword ptr [ebp-4],eax 这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p 么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie信息去进行释放内存的工作。 好了,我们回到我们的主题:堆和栈究竟有什么区别? 主要的区别由以下几点: 1、管理方式不同; 2、空间大小不同; 3、能否产生碎片不同; 4、生长方向不同;

详解堆栈的几种实现方法——C语言版

详解堆栈的几种实现方法——C语言版 基本的抽象数据类型(ADT)是编写C程序必要的过程,这类ADT有链表、堆栈、队列和树等,本文主要讲解下堆栈的几种实现方法以及他们的优缺点。 堆栈(stack)的显著特点是后进先出(Last-In First-Out, LIFO),其实现的方法有三种可选方案:静态数组、动态分配的数组、动态分配的链式结构。 静态数组:特点是要求结构的长度固定,而且长度在编译时候就得确定。其优点是结构简单,实现起来方便而不容易出错。而缺点就是不够灵活以及固定长度不容易控制,适用于知道明确长度的场合。 动态数组:特点是长度可以在运行时候才确定以及可以更改原来数组的长度。优点是灵活,缺点是由此会增加程序的复杂性。 链式结构:特点是无长度上线,需要的时候再申请分配内存空间,可最大程度上实现灵活性。缺点是链式结构的链接字段需要消耗一定的内存,在链式结构中访问一个特定元素的效率不如数组。 首先先确定一个堆栈接口的头文件,里面包含了各个方案下的函数原型,放在一起是为了实现程序的模块化以及便于修改。然后再接着分别介绍各个方案的具体实施方法。 堆栈接口stack.h文件代码: [cpp]view plaincopy 1./* 2.** 堆栈模块的接口 stack.h 3.*/ 4.#include 5. 6.#define STACK_TYPE int /* 堆栈所存储的值的数据类型 */ 7. 8./* 9.** 函数原型:create_stack 10.** 创建堆栈,参数指定堆栈可以保存多少个元素。 11.** 注意:此函数只适用于动态分配数组形式的堆栈。 12.*/ 13.void create_stack(size_t size); 14. 15./* 16.** 函数原型:destroy_stack 17.** 销毁一个堆栈,释放堆栈所适用的内存。 18.** 注意:此函数只适用于动态分配数组和链式结构的堆栈。 19.*/ 20.void destroy_stack(void); 21. 22./*

相关主题
文本预览
相关文档 最新文档