在C语言中,堆栈是一个很重要的概念,堆和栈是两种不同的数据结构,合称为堆栈。堆是动态内存分配,栈是自动内存管理。以下是两者的区别和使用方法。
1.堆和栈的通俗理解
栈:后进先出的数据结构,比如我们一层一层的叠放箱子,都会遵循一个时间顺序来叠放,先放的在下面,后放的在上面,我们如果要取出其中一个箱子,前提就是先把最近压在这个箱子上面的箱子先搬走,才能拿走到这个箱子。遵循一个后进先出的原则。
堆:堆是一种经过排序的树形数据结构,每个结点都有一个值。堆的存取是随意,这就如同我们在图书馆的书架上取书,虽然书的摆放是有顺序的,但是我们想取任意一本时不必像栈一样,先取出前面所有的书,书架这种机制不同于箱子,我们可以直接取出我们想要的书。
2.堆和栈技术上的理解
- 管理方式不同:栈是由编译器自动管理,包括分配和释放;堆是手动管理的,使用malloc, realloc, calloc, free进行分配和释放。
- 空间大小不同:栈的空间通常较小,用于存储局部变量和函数调用信息;堆的空间较大,可以从操作系统申请大块内存。
- 速度不同:栈的速度快,因为其数据访问通常比堆快;堆速度较慢,且分配和释放需要额外的工作。
- 分配方式不同:栈是向下增长的,向低地址方向增长;堆是向上增长的,向高地址方向增长。
// 使用栈
void stack() {
int a; // 局部变量,存储在栈上
int b = 10; // 初始化局部变量
a = b; // 将b的值赋给a
}
// 使用堆
void heap() {
int p; // 指针变量本身存储在栈上
p = (int)malloc(sizeof(int)); // 动态分配内存,存储在堆上
if(p != NULL) {
*p = 10; // 给分配的内存赋值
free(p); // 释放分配的内存
}
}
3.堆和栈的工作区分
内存区分:
栈:是系统自动分配,所以速度快,但是程序员无法自行控制。
堆:是需要程序员自行分配,所以速度慢,容易产生内存碎片,但是易控制。
大小限制:
栈:是向低地址扩展的数据结构,是一块连续的内存的区域。栈的最大容量是系统预先规定好的,如果申请的空间超过栈的剩余空间时就会报错栈溢出。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。