棧導論

 本篇文章主要起到引子的做用,而並不是去研究棧結構、或者說堆棧在操做系統內部的機制。
 學習好久的棧,經過彙編語言來學習棧、C數據結構去實現的棧,正由於感受棧太過於深秒,沒法表述更好,因此只是一個導論,說說學習心得。
棧的特色:後進先出(Last in first out),這就是棧的精髓,咱們知道在內存中其實都是線性存儲,他能夠是棧段,也能夠是數據段,更能夠是其他的內存空間
 以8086CPU(16位)舉列說明,只要是被ss:sp(基礎段寄存器+偏移地址)所指向的地址,這就是棧內存,那麼經過上面敘述咱們應該考慮,居然沒有具體的告訴那是棧內存,那不是無限大?你能夠這樣理解,凡是電腦可以尋址到的內存空間(必須是段寄存器ss+偏移地址)就能夠認爲是棧內存,那麼棧溢出,棧下線等問題就成了安全的重要話題。
 CPU是如何來進行入棧、出棧等操做呢? 首先棧底、棧頂兩個概念。棧底也就是棧的底部,棧頂也就是棧的最高點,都說了內存中沒有說哪個空間是棧的空間,何來的棧頂與棧底呢?其實就是咱們人爲設置的,你們想象出來的,這一點與先進後出的思想大同小異,更是棧的思想,只要讓這些數據遵循着這些規則,那麼就是棧。初始化棧咱們通常認爲都是把指針指向棧底,其實否則在內存中寄存器會指向棧底的下一個單元,爲何?
 一、Push操做,內存中高地址在下,低地址在上面(豎線),首先入棧操做首先會sp(依靠偏移地址來尋址)減偏移地址,爲何是減,由於壓棧的元素是壓棧到棧底,下面是高地址!
 二、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);

}

思想纔是王道,語言是用來實現思想的價值,一體一用。安全

相關文章
相關標籤/搜索