C语言堆和栈

合集下载

单片机C语言 必知的数据存储与程序编写知识 附单片机应用编程知识介绍

单片机C语言 必知的数据存储与程序编写知识 附单片机应用编程知识介绍

一、五大内存分区内存分成5个区,它们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

1、栈区(StaCk):FIFo就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。

里面的变量通常是局部变量、函数参数等。

2、堆区(heap):就是那些由new分配的内存块,它们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。

如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

3、自由存储区:就是那些由malloc等分配的内存块,它和堆是十分相似的,不过它是用free 来结束自己的生命。

4、全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

5、常量存储区:这是一块比较特殊的存储区,它们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)code/data/stack内存主要分为代码段,数据段和堆栈。

代码段放程序代码,属于只读内存。

数据段存放全局变量,静态变量,常量等,堆里存放自己malloc或new出来的变量,其他变量就存放在栈里,堆栈之间空间是有浮动的。

数据段的内存会到程序执行完才释放。

调用函数先找到函数的入口地址,然后计算给函数的形参和临时变量在栈里分配空间,拷贝实参的副本传给形参,然后进行压栈操作,函数执行完再进行弹栈操作。

字符常量一般放在数据段,而且相同的字符常量只会存一份。

二、C语言程序的存储区域1、由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-连接三个阶段。

编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序形成二进制机器代码,连接过程则将各个源文件生成的二进制机器代码文件组合成一个文件。

2、C语言编写的程序经过编译-连接后,将形成一个统一文件,它由几个部分组成。

堆、栈的概念与理解

堆、栈的概念与理解

1、从数据结构层次理解,栈是一种先进后出的线性表,只要符合先进后出的原则的线性表都是栈。至于采用的存储方式(实现方式)是顺序存储(顺序栈)还是链式存储(链式栈)是没有关系的。堆则是二叉树的一种,有最大堆最小堆,排序算法中有常用的堆排序。
2、从系统层次理解,栈是系统为运行的程序分配的先进后出的存储区域。在学习bootloader时知道,在上电后初始化阶段要为各个工作模式下分配堆 栈,这里的堆栈实际上就是指stack,堆栈的说法只是因为历史的原因。在执行函数时,函数内部局部变量的存储单元可以在栈上创建(针对CISC架构而 言,RISC架构下,局部变量的存储单元是在寄存器上创建),函数执行结束时这些存储单元自动被释放。堆是系统管理的可以被程序利用的全局存储空间,动态 内存分配就是从堆上分配。
什么是堆什么是栈
一 英文名称
堆和栈是C/C++编程中经常遇到的两个基本概念。先看一下它们的英文表示:
堆――heap
栈――stack
二 从数据结构和系统两个层次理解
在具体的C/C++编程框架中,这两个概念并不是并行的。深入到汇编级进行研究就会发现,栈是机器系统提供的数据结构,而堆是由C/C++函数库提供的。这两个概念可以从数据结构和系统两个层次去理解:
具体地说,现在计算机(串行执行机制),都直接在代码层次支持栈这种数据结构。这体现在,有专门的寄存器指向栈所在的地址,有专门的机器指令完成数据入栈 出栈的操作。比如ARM指令中的stmfd和ldmfd。因为栈内存分配运算内置于处理器的指令集中,所以效率很高,但是支持的数据有限,一般是整数、指 针、浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构。在CISC中,对子程序的调用就是利用栈来完成的。C/C++中的自动变量也是直接利 用栈的例子,这就是为什么当函数返回时,该函数的自动变量失效的原因(因为栈恢复了调用前的状态)。在RISC下,这些都是通过寄存器来完成的。这些留待 第二部分总结中详细阐述。

堆栈及静态数据区详解

堆栈及静态数据区详解

堆、栈及静态数据区详解五大内存分区在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 14h0040102A call operator new (00401060)0040102F add esp,400401032 mov dword ptr [ebp-8],eax00401035 mov eax,dword ptr [ebp-8]00401038 mov dword ptr [ebp-4],eax这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete []p,这是为了告诉编译器:我删除的是一个数组,VC6就会根据相应的Cookie 信息去进行释放内存的工作。

c堆空间和栈空间默认值

c堆空间和栈空间默认值

c堆空间和栈空间默认值C语言是一门广泛应用于嵌入式系统、操作系统及系统编程领域的编程语言。

它的简单易学、代码高效、性能出色及可移植性强等特点,使得它在各个领域得到了广泛的应用。

但是,一些仅在C语言中才存在的问题常常令人困扰,比如说堆空间和栈空间的默认值问题。

下面,我们就来仔细讲讲。

一、什么是堆空间和栈空间?堆空间和栈空间是程序运行时的两个不同的内存区域。

简单来说,栈空间主要用于存放局部变量、函数参数、返回地址等数据,而堆空间可以让程序员自己控制动态分配和释放内存。

同时,堆空间还可以用来存储全局变量和静态变量等。

二、堆空间和栈空间的默认值在C语言中,堆空间和栈空间的大小是有限制的。

且不说堆空间几乎是没有限制的,栈空间大小却是固定的(根据不同的编译器、操作系统有不同的限制,一般在1MB~2MB之间)。

当栈空间的大小超过限制时,会发生栈溢出的情况,程序会崩溃。

因此,在编程时,需要根据实际情况合理分配内存空间,避免出现这种情况。

对于堆空间而言,它的默认值是不确定的。

在一些编译器中,堆空间默认的大小是0,也就是说,程序员必须手动为它分配空间。

这种编译器通常是为了减少程序的运行内存的占用,提高程序的效率。

而在另一些编译器中,堆空间默认大小是非0的,但是其值也是不确定的。

在这种情况下,程序员也必须手动为堆空间分配空间。

三、堆空间和栈空间的手动分配由于堆空间和栈空间的默认值存在不确定性,因此程序员必须手动为它们分配空间。

在C语言中,通过malloc()函数和free()函数可以实现堆空间的手动分配和释放。

而栈空间的手动分配主要通过函数调用时传递参数实现,因为函数的参数在栈中分配。

堆空间的分配主要是在需要使用动态内存的时候进行。

动态内存的使用可以解决一些静态内存无法解决的问题,例如存储用户输入的字符串内容、存储较大的数据表等。

在使用动态内存时,程序员需要注意动态内存分配后一定要及时释放,否则会出现内存泄漏的问题。

c语言的内存结构

c语言的内存结构

c语言的内存结构C语言是一种高级编程语言,但实际上在计算机中运行时,C语言程序会被编译成可执行文件,然后在计算机内存中运行。

因此,了解C 语言的内存结构对于理解C程序的运行及性能优化至关重要。

C语言的内存结构主要可以分为以下几个部分:栈(Stack)、堆(Heap)、全局内存(Global Memory)和代码区(Code Segment)。

首先是栈(Stack),栈是一种自动分配和释放内存的数据结构。

它用于存储局部变量、函数参数和函数调用信息等。

栈的特点是后进先出(LIFO),也就是最后进入的数据最先被释放。

栈的大小在程序运行时是固定的,一般由编译器设置。

栈的操作速度较快,但内存空间有限。

其次是堆(Heap),堆是一种动态分配和释放内存的数据结构。

它用于存储动态分配的变量、数据结构和对象等。

堆的大小一般由操作系统管理,并且可以在运行时进行动态扩展。

堆的操作相对较慢,因为需要手动分配和释放内存,并且容易产生内存碎片。

全局内存(Global Memory)是用于存储全局变量和静态变量的区域。

全局变量在程序的生命周期内都存在,并且可以在多个函数之间共享。

静态变量作用于其所在的函数内,但是生命周期与全局变量相同。

全局内存由编译器进行分配和管理。

代码区(Code Segment)存储了程序的指令集合,它是只读的。

在程序运行时,代码区的指令会被一条一条地执行。

代码区的大小由编译器决定,并且在程序执行过程中不能修改。

此外,C语言还具有特殊的内存区域,如常量区和字符串常量区。

常量区用于存储常量数据,如字符串常量和全局常量等。

常量区的数据是只读的,且在程序的整个生命周期内存在。

字符串常量区是常量区的一个子区域,用于存储字符串常量。

在C语言中,内存分配和释放是程序员的责任。

通过使用malloc和free等函数,程序员可以在堆中动态地分配和释放内存,从而灵活地管理程序的内存使用。

不过,应当注意避免内存泄漏和野指针等问题,以免出现内存错误和性能问题。

c语言cpu分配内存的原则

c语言cpu分配内存的原则

c语言cpu分配内存的原则:
以下是一些关于C语言中内存分配的原则:
1.静态存储区:这部分内存是在程序编译时分配的,包括全局变量和静态变量。

这些
变量的生命周期是整个程序的执行期间。

2.栈内存:这部分内存是在程序执行期间动态分配的,主要用来存储函数调用的局部
变量和函数参数。

当函数执行结束时,这部分内存会自动释放。

3.堆内存:这是动态内存分配区域,通过malloc,calloc等函数分配。

当不再需要这部
分内存时,应使用free函数释放。

需要注意的是,如果不正确地使用这些函数(例如,试图释放同一块内存两次或者在释放内存后继续使用它),可能会导致程序崩溃或未定义的行为。

4.代码段:也称为文本段,这是用来存储程序的二进制代码的区域。

这部分内存通常
不可写,因为它是只读的,以防止程序意外地修改其指令。

5.运行时内存分配:C语言标准库提供了一些函数用于在运行时动态分配和释放内存,
如malloc()、calloc()、realloc()和free()。

这些函数允许程序员在运行时分配和释放内存,这在处理大量数据或需要根据程序运行情况动态调整数据结构大小时非常有用。

C语言中堆的名词解释

C语言中堆的名词解释

C语言中堆的名词解释堆(Heap)是C语言中的一种动态内存分配方式,它相对于栈(Stack)来说,拥有更大的内存空间并且能够存储具有更长生命周期的数据。

在本文中,我们将解释堆的概念、特性以及在C语言中的应用。

一、堆的概念和特性堆是C语言中一块动态分配的内存区域,用于存储程序运行期间需要长时间保留的数据。

与栈不同,堆的内存分配和释放并不自动管理,而是需要通过程序员手动控制。

堆的主要特性可以概括为以下几点:1. 大小可变:堆的大小取决于操作系统的内存限制,可以动态地增加或缩小。

2. 不连续性:堆内存中的数据块可以被随意分配和释放,它们的位置通常是不连续的。

3. 长生命周期:堆中分配的内存空间在程序运行期间一直存在,直到显式地释放。

4. 存储动态数据:堆用于存储运行时动态创建的数据,例如对象、数组、链表等。

二、堆的内存分配在C语言中,使用malloc函数来动态分配堆内存。

malloc的完整形式是memory allocation(内存分配),其原型如下:```cvoid* malloc(size_t size);malloc函数接受一个size_t类型的参数,表示需要分配的内存空间大小,返回一个void指针,指向分配的内存起始地址。

若分配失败,则返回一个空指针NULL。

以下是一个使用malloc分配堆内存的示例:```cint* ptr = (int*) malloc(sizeof(int));```在上述示例中,我们使用malloc函数分配了一个int类型的内存空间并将其地址赋值给了ptr指针。

这样,我们就可以通过访问ptr来操作这个堆内存空间。

需要注意的是,使用malloc函数分配的堆内存必须在使用完毕后通过调用free 函数来显式地释放,以避免内存泄漏。

free函数的原型如下:```cvoid free(void* ptr);```free函数接受一个void指针作为参数,指向需要释放的堆内存的起始地址。

C语言实现堆栈(自己的)

C语言实现堆栈(自己的)

C语⾔实现堆栈(⾃⼰的)stack.h#ifndef __STACK_H__#define __STACK_H__#include <stdio.h>#include <stdlib.h>#include <stdbool.h>typedef int ElementType;struct SNode {ElementType *Data; /* 存储元素的数组 */int Top; /* 栈顶指针 */int MaxSize; /* 堆栈最⼤容量 */};typedef struct SNode *Stack;Stack CreateStack( int MaxSize ); //建⽴结构体堆栈bool IsFull( Stack S ); //判断堆栈是是否溢出bool Push( Stack S, ElementType X ); //压栈bool IsEmpty( Stack S ); //判断堆栈是是否为空ElementType Pop( Stack S ); //出栈#endifstack.c#include "stack.h"#include "sys.h"u8 Choose_Stack_Flag=0; //未检测到加减符号时候,0:⼀个结构体,检测到1:另⼀个结构体Stack CreateStack( int MaxSize ){Stack S = (Stack)malloc(sizeof(struct SNode));S->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));S->Top = -1;S->MaxSize = MaxSize;return S;}bool IsFull( Stack S ){return (S->Top == S->MaxSize-1);}bool Push( Stack S, ElementType X ){if ( IsFull(S) ) {printf("堆栈满");return false;}else {S->Data[++(S->Top)] = X;return true;}}bool IsEmpty( Stack S ){return (S->Top == -1);}ElementType Pop( Stack S ){if ( IsEmpty(S) ) {printf("堆栈空");return ERROR; /* ERROR是ElementType的特殊值,标志错误 ERROR 0 */}elsereturn ( S->Data[(S->Top)--] );}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到。

但对于很多的初学着来说,堆栈是一个很模糊的概念。

堆栈:一种数据结构、一个在程序运
行时用于存放的地方,这可能是很多初学者的认识,因为我曾经就是这么想的和汇编语言中
的堆栈一词混为一谈。

我身边的一些编程的朋友以及在网上看帖遇到的朋友中有好多也说不
清堆栈,所以我想有必要给大家分享一下我对堆栈的看法,有说的不对的地方请朋友们不吝
赐教,这对于大家学习会有很大帮助。

首先在数据结构上要知道堆栈,尽管我们这么称呼它,但实际上堆栈是两种数据结构:堆和栈。

堆和栈都是一种数据项按序排列的数据结构。

我们先从大家比较熟悉的栈说起吧,它是一种具有后进先出性质的数据结构,也就是说
后存放的先取,先存放的后取。

这就如同我们要取出放在箱子里面底下的东西(放入的比较
早的物体),我们首先要移开压在它上面的物体(放入的比较晚的物体)。

而堆就不同了,堆
是一种经过排序的树形数据结构,每个结点都有一个值。

通常我们所说的堆的数据结构,是
指二叉堆。

堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。

由于
堆的这个特性,常用来实现优先队列,堆的存取是随意,这就如同我们在图书馆的书架上取
书,虽然书的摆放是有顺序的,但是我们想取任意一本时不必像栈一样,先取出前面所有的
书,书架这种机制不同于箱子,我们可以直接取出我们想要的书。

然而我要说的重点并不在这,我要说的堆和栈并不是数据结构的堆和栈,之所以要说数
据结构的堆和栈是为了和后面我要说的堆区和栈区区别开来,请大家一定要注意。

下面就说说C语言程序内存分配中的堆和栈,这里有必要把内存分配也提一下,大家不
要嫌我啰嗦,一般情况下程序存放在Rom或Flash中,运行时需要拷到内存中执行,内存会分
别存储不同的信息,如下图所示:
内存中的栈区处于相对较高的地址以地址的增长方向为上的话,栈地址是向下增长的,
栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。

另外还有静态区是分配静态变量,全局变量空间的;只读区是分配常量和程序代码空间的;以及其他一些分区。

来看一个网上很流行的经典例子:
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); 堆
}
不知道你是否有点明白了,堆和栈的第一个区别就是申请方式不同:栈(英文名称
是stack)是系统自动分配空间的,例如我们定义一个char a;系统会自动在栈上为其开辟空间。

而堆(英文名称是heap)则是程序员根据需要自己申请的空间,例如malloc(10);开辟十个字节的空间。

由于栈上的空间是自动分配自动回收的,所以栈上的数据的生存周期只是在函数的运行过程中,运行后就释放掉,不可以再访问。

而堆上的数据只要程序员不释放空间,就一直可以访问到,不过
缺点是一旦忘记释放会造成内存泄露。

还有其他的一些区
别我认为网上的朋友总结的不错这里转述一下:
1.申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。

另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

也就是说堆会在申请后还要做一些后续的工作这就会引出申请效率的问题。

2.申请效率的比较
栈:由系统自动分配,速度较快。

但程序员是无法控制的。

堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。

3.申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。

这句话的意思
是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的
说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示
overflow。

因此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。

这是由于系统是用链表来存储的
空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。

堆的大小受限
于计算机系统中有效的虚拟内存。

由此可见,堆获得的空间比较灵活,也比较大。

4.堆和栈中的存储内容
栈:在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下
一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左
入栈的,然后是函数中的局部变量。

注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的
地址,也就是主函数中的下一条指令,程序由该点继续运行。

堆:一般是在堆的头部用一个字节存放堆的大小。

堆中的具体内容有程序员安排。

5.存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。

比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码
10: a = c[1];
00401067 8A 4D F1 movcl,byteptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC movedx,dwordptr [ebp-14h]
00401070 8A 42 01 moval,byteptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
堆和栈的区别可以引用一位前辈的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了
就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自
由度小。

使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

比喻很形象,说的很通俗易懂,不知道你是否有点收获。

本文来自CSDN博客,转载请标明出处:/lfj200701/archive/2010/06/11/5665165.aspx。

相关文档
最新文档