本篇文章主要起到引子的作用,而并非去研究栈结构、或者说堆栈在操作系统内部的机制。  学习很久的栈,通过汇编语言来学习栈、C数据结构去实现的栈,正因为感觉栈太过于深秒,无法表述更好,所以只是一个导论,说说学习心得。  栈的特点:后进先出(Last in first out),这就是栈的精髓,我们知道在内存中其实都是线性存储,他可以是栈段,也可以是数据段,更可以是其余的内存空间。  以8086CPU(16位)举列说明,只要是被ss:sp(基础段寄存器+偏移地址)所指向的地址,这就是栈内存,那么通过上面叙述我们应该考虑,竟然没有具体的告诉那是栈内存,那不是无限大?你可以这样理解,凡是电脑能够寻址到的内存空间(必须是段寄存器ss+偏移地址)就可以认为是栈内存,那么栈溢出,栈下线等问题就成了安全的重要话题。  CPU是如何来进行入栈、出栈等操作呢? 首先栈底、栈顶两个概念。栈底也就是栈的底部,栈顶也就是栈的最高点,都说了内存中没有说哪一个空间是栈的空间,**何来的栈顶与栈底呢?其实就是我们人为设置的,大家想象出来的,这一点与先进后出的思想大同小异,更是栈的思想,只要让这些数据遵循着这些规则,那么就是栈。**初始化栈我们一般认为都是把指针指向栈底,其实不然在内存中寄存器会指向栈底的下一个单元,为什么?  1、Push操作,内存中高地址在下,低地址在上面(竖线),首先入栈操作首先会sp(依靠偏移地址来寻址)减偏移地址,为什么是减,因为压栈的元素是压栈到栈底,下面是高地址!  2、Pop操作,原理相同,出栈操作,就是把里面的数据从上往外拿,后进先出嘛,所以空间是指针是来下面移动的(这个好像,那个纸画一画就出来了),sp就要+2,正好与压栈相反。 当然这些操作都要认为的去边界定义和代码中做一些处理机制。 注意:任意时刻,ss:sp都是指向栈顶(栈底只是我们想象出的一个栈段,其实不存在)  说了那么多关于内存中栈的知识,还是叫汇编知识吧,说一说C语言中数据结构,过程语言也好高级语言也好,其实都必须遵守后进先出的思想,才可以叫做栈,C或者高级语言就可以进行越界的限制(内存申请及条件判断等)。 栈可以干些什么?可以干很多事,每个函数调用基本都会用到栈、当转移指令的时候,也都会把IP保存到栈中(call,ret等指令),逆波兰、二进制转换、加密、递归等等都可以用栈数据结构高效、便捷的去实现。  栈的基本操作无非,初始化、压栈(Push)、出栈(Pop)、遍历栈、清空栈、销毁栈(与清空栈不是一个概念),清空栈就像欺骗内存,并非数据都给从内存清理,类似于格式化磁盘这样,让操作系统感觉这块内存没有数据,其实写入数据覆盖原来数据。 也可以分为静态栈、动态栈,怎么叫都行。用数组就是静态,用链表就是动态,不过注意: 一定都要遵循后进先出的原则,否则就算写的特别灵活,出栈直接越过低位取高位,那样就违背栈的意愿,就算不上栈了!  下面是一段二进制转换代码(学习中的小练题很有意思,分享给大家),基本栈操作就不分享了,大家代码大同小异,网上有更多前辈写的高质量代码值得大家参考

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#define STACK_INIT_SIZE 20
#define STACKINCREMENT 0

typedef char ElemType;
typedef struct 
{
	ElemType *top;
	ElemType *bottom;
	int stackSize;
}sqStack;

void Init_stack(sqStack *s);
void Push_stack(sqStack *s, ElemType e);
void Pop(sqStack *s, ElemType *e);
int StackLength(sqStack s);

int main(void)
{
	ElemType c;
	sqStack s;
	int len, i, sum = 0;
	
	Init_stack(&s);

	printf("请输入二进制数,输入#符号表示结束!\n");
	scanf("%c", &c);
	while ( c != '#' )
	{
		Push_stack(&s, c);
		scanf("%c", &c);
	}

	getchar();

	len = StackLength(s);
	printf("栈的当前容量是: %d\n",len);

	for(i = 0; i < len; i++)
	{
		Pop(&s, &c);
		sum = sum + (c-48) * pow(2, i);
	}

	printf("二进制转换10进制之后数值: %d\n",sum);
	

	return 0;
}

void Init_stack(sqStack *s)
{
	s->bottom = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
	if( !s->bottom )
	{
		exit(-1);
	}

	s->top = s->bottom;
	s->stackSize = STACK_INIT_SIZE;			//最大容量
}


void Push_stack(sqStack *s, ElemType e)
{
	if( s->top - s->bottom >= s->stackSize )
	{
		s->bottom = (ElemType *)realloc(s->bottom, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
		if( !s->bottom )
		{
			exit(-1);
		}
	}

	*(s->top) = e;
	s->top++;
}


void Pop(sqStack *s, ElemType *e)
{
	if( s->top == s->bottom )
	{
		return;
	}

	*e = *--(s->top);
}


int StackLength(sqStack s)
{
	return (s.top - s.bottom);

}

思想才是王道,语言是用来实现思想的价值,一体一用。