
🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言 🔥专栏: 《C语言从零开始到精通》 《C语言编程实战》 《数据结构与算法》 《小游戏与项目》 💪格言:做好你自己,你才能吸引更多人,并与他们共赢,这才是你最好的成长方式。
在计算机的学习中,我们老是听到内存上有栈区、堆区、静态区等等,那么这个内存上的栈究竟是什么呢?或者说栈这个东西有什么特点?为什么又听说栈也是一种数据结构呢?本片文章就围绕栈的内部结构以及内存栈区与数据结构栈的关系展开叙述,解答这些疑惑
内存中的栈区(Stack Memory)是程序运行时内存空间的核心分区之一,由操作系统/编译器自动管理,核心特点是“先进后出(LIFO)”,专门用于处理函数调用、局部变量等临时数据,是程序执行的基础支撑。
先进后出作为栈最基本也是最重要的性质,我们在稍后的数据结构栈内容仔细讲解,现在可以稍微记一下
栈区是线程专属的内存分区(每个线程都有独立的栈),大小通常是固定的(默认几MB,可通过编译器/系统配置调整),用于存储函数调用过程中的临时数据,随函数的“调用”自动分配、“返回”自动释放,无需开发者手动管理。
不了解内存中分区的话可以配合下图食用:

栈区的核心存储对象是栈帧(Stack Frame)——每个函数调用时,系统会在栈区分配一块“栈帧”,存储该函数的:
func(10, 20) 中的 10 20);int a = 5; 中的 a);栈区的操作只有“压栈(Push)”和“弹栈(Pop)”:
举个直观例子(函数调用过程):
// 函数A调用函数B
void B(int x) {
int y = x + 1; // y是B的局部变量,存在B的栈帧中
}
void A() {
int a = 10; // a是A的局部变量,存在A的栈帧中
B(a); // 调用B,分配B的栈帧(入栈)
} // A返回,A的栈帧被释放(出栈)执行流程中栈的变化:
A() → 压入 A 的栈帧(存储 a=10、返回地址等);A 调用 B(a) → 压入 B 的栈帧(存储参数 x=10、局部变量 y=11 等);B 执行完返回 → 弹出 B 的栈帧;A 执行完返回 → 弹出 A 的栈帧;
最终栈回到初始状态。数据结构的栈(Stack)是一种遵循“先进后出(LIFO,Last In First Out)”规则的线性逻辑结构——核心特点是“只允许在一端(栈顶)进行数据的插入(入栈)和删除(出栈)操作”,另一端(栈底)固定不可直接操作。
也就是说栈相当于是只有一个开口的直筒,所谓的 LIFO 特性就是先放进去的话在下面,导致后放进去的东西先拿出来的一种特性。
top变量)记录当前栈顶位置;top=0或top=-1,取决于实现约定)。操作名 | 功能描述 | 时间复杂度 |
|---|---|---|
Push(入栈) | 在栈顶插入一个新元素,栈顶标记更新 | O(1) |
Pop(出栈) | 删除栈顶元素(不返回值,或返回被删元素),栈顶标记更新 | O(1) |
Top(取栈顶) | 读取栈顶元素,但不删除(栈状态不变) | O(1) |
Empty(判空) | 判断栈是否为空(空返回true,非空返回false) | O(1) |
Size(求大小):返回栈中有效元素的个数;Destroy(销毁):释放栈占用的内存(动态实现时必需,避免内存泄漏)。数据结构的栈是“逻辑规则”,需要借助具体的物理存储载体实现,常见两种方式:
ptr)作为存储容器,top记录栈顶位置,capacity记录数组容量;ptr[top-1]访问),实现简单;因为动态数组实现的栈其实是类似一个简单的线性表,这里就直接在这块插入代码供大家学习:
typedef int STDatatype;
typedef struct Stack
{
STDatatype* ptr;
int top;
int capacity;
}Stack;
//初始化与销毁
void StackInit(Stack* ps);
void StackDestroy(Stack* ps);
//入栈与出栈
void StackPush(Stack* ps,STDatatype x);
void StackPop(Stack* ps);
//查看顶端元素
STDatatype StackTop(Stack* ps);
//判空
bool StackEmpty(Stack* ps);
//有效元素个数
int StackSize(Stack* ps);//初始化与销毁
void StackInit(Stack* ps)
{
assert(ps);
ps->ptr = NULL;
ps->capacity = 0;
//指向栈顶的下一个位置
ps->top = 0;
}
void StackDestroy(Stack* ps)
{
assert(ps);
free(ps->ptr);
ps->ptr = NULL;
ps->capacity = ps->top = 0;
}
//入栈与出栈
void StackPush(Stack* ps, STDatatype x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : (2 * ps->capacity);
STDatatype* tmp = (STDatatype*)realloc(ps->ptr,newcapacity * sizeof(STDatatype));
if (tmp == NULL)
{
perror("realloc");
return;
}
ps->ptr = tmp;
ps->capacity = newcapacity;
}
ps->ptr[ps->top] = x;
ps->top++;
}
void StackPop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top-- ;
}
//查看顶端元素
STDatatype StackTop(Stack* ps)
{
assert(ps);
assert(ps->top > 0);
return ps->ptr[ps->top - 1];
}
//判空
bool StackEmpty(Stack* ps)
{
assert(ps);
return ps->top == 0;
}
//有效元素个数
int StackSize(Stack* ps)
{
assert(ps);
return ps->top;
}正因为“先进后出”的特性,栈在编程和算法中应用极广:
() [] {}是否成对);