堆栈指针理解
堆栈指针sp在片内RAM128B中开辟栈区,并随时跟踪栈顶地址。它是按"先进后出"的原则存取数据。开机复位后,单片机栈底地址为07H。
主要用来保存暂时数据,局部变量和中断/自程序的返回地址。
堆栈指针总是指向栈顶元素。所以数据入栈的时候,堆栈指针先加1,再压栈。向上增长方式。和计算机的方式一样。
出栈的时候先弹出数据,堆栈指针再减1。
假设堆栈的实现是往上长的(就是说往顶的方向长,事实上质是你的栈底是定死的不能动,入栈的东西仅仅能不断往上叠,这就像你在书桌上放书一样,桌底是定死的,所以你的书仅仅能一本一本地往上堆,往上长),计算机内部的堆栈的实现採取的就是这样的模式,所以就得像你说的那样,“先改动指针,然后插入数据,出栈时刚好相反”,由于你堆栈指针指向的总是栈顶元素,栈底不能动,所以数据入栈前要先改动指针使它指向新的空余空间然后再把数据存进去,出栈的时候自然相反。
然而,假设堆栈的实现是往下长的(就是说你每压一个元素入栈,栈底就自己主动下移一个元素的位置,事实上质就是这样的堆栈模型是一个“无底洞”型),这个时候,你的栈顶就变成了定死的,你就能够先压入元素,然后再改动指针。由于你的栈底是无限的,你压入一个元素,新的元素就代替先前的栈顶元素占领栈顶的位置,那么你先前的指向栈顶元素的指针这个时候就该改动让它指向这个新的栈顶元素了。
以下的就是对“无底洞”型堆栈的一种实现的描写叙述:
压栈(入栈):将对象或者数据压入栈中,更新栈顶指针,使其指向最后入栈的对象或数据。
弹栈(出栈):返回栈顶指向的对象或数据,并从栈中删除该对象或数据,更新栈顶。
话说回来,计算机内部肯定选第一种模型,不会选另外一种,由于另外一种模型,每压入一个新的元素,都须要把之前堆栈里的全部元素总体下移动一个元素的位置,腾出栈顶元素的位置让新的元素进来,这样的平移但是一笔不小的开销啊!但是并非说“无底洞”模型就没办法实现了,事实上它能够通过第一种模型来模拟的,每须要压入一个新的元素的时候,就先开辟一个空间,数据存入这个空间,然后再改动栈顶元素指针使其指向这个新的栈顶元素。
换句话说,用链表的话,仅仅要有足够的空间可开辟出来作为一个节点,那么两种堆栈模型都能实现(当然“无底洞”型还是如我上面说的那样用第一种模拟出来的,否则平移的工作量相当可观),假设用数组,因为数组在内存中是连续分配出来的空间,用第一种模型更自然一些