在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

棧是一種LIFO后入先出的什么數據結構?

lhl545545 ? 來源:玩轉單片機 ? 作者:玩轉單片機 ? 2020-06-09 09:26 ? 次閱讀

沒有比這個更直觀的啦,棧是一種受限的數據結構模型,其數據總是只能在頂部追加,利用一個指針進行索引,頂端叫棧頂,相對的一端底部稱為棧底。棧是一種LIFO后入先出的數據結構。

棧就兩種操作:

PUSH,壓棧,向棧內加入數據,

POP,出棧

再進一步探討:

首先將棧與堆分清,從看到這篇文章開始,我建議你不要把堆和棧連在一起叫,棧是棧,堆是堆,這是兩回事,別混為一談!(堆本文不深入討論)

從C/C++編程語言的角度來看:

相同點:都是一片內存區,在鏈接時指定棧區/堆區的位置以及大小。

不同點:

棧:由編譯器分配,存放函數的參數值,局部變量,寄存器組(不同的單片機/處理器各有不同)、函數調用參數傳遞、中斷異常產生時須保存處理器狀態的寄存器值等

堆:由程序員分配釋放,對于C而言,malloc、realloc/free進行分配/釋放,對C++而言,由new/delete分配/釋放。

為啥用

棧這個數據模型的應用價值是什么呢?先來看一下單片機內部的可能有哪些棧應用?以STM32為例,參考IAR C/C++ Development Guide,P207

處理器模式建議段名描述

SupervisorSVC_STACK操作系統

IRQIRQ_STACK通用(IRQ)中斷處理程序的堆棧。

FIQFIQ_STACK用于高速(FIQ)中斷處理程序的堆棧。

UndefinedUND_STACK堆棧用于未定義的指令中斷。支持硬件協處理器和指令集擴展的軟件仿真

AbortABT_STACK用于指令獲取和數據訪問存儲器中止中斷處理程序的堆棧。

如果使用RTOS還有任務棧,如果是Linux,其內核線程同樣也需要棧的支持,等等這一切的一切棧,其本質上都是利用了棧數據模型的LIFO后入先出的特性,一個典型應用場景就是比如做一件事情做到一半而要轉而去做另外一件事,對于芯片編程而言,就需要將當前的工作做個暫存,等另外一件事情做完了,再接著回來繼續做。那么怎么做到呢,以一個中斷處理為例,要記住當前的工作態有哪些信息需要暫存呢?PC指針,局部變量等就被壓入棧,再將中斷服務程序地址導入PC指針,進而去執行中斷服務程序,待中斷處理完畢,在將棧里的內容按照后入先出彈出到對應的寄存器就恢復了原程序的現場,進而繼續執行。

怎么用

棧在哪里定義大小,定多大合適?這可能很多剛接觸單片機開發的同學不是太清楚,下面就將比較常見的IAR開發環境為例如何定義棧定義棧大小的地方說明一下,這里以IAR8.4.1為例,有兩種方式可以進行棧大小設置。

IDE設置

為了更加清楚明了,制作了一個GIF操作展示視頻,在stack/heap中就可以設置了,其中stack用于設置棧區大小,heap用于設置堆大小。

這個demo中設置了其棧的大小為0x200,堆的大小為0x400,全編譯后,檢查map文件就印證了棧/堆的大小如預期所修改。

鏈接配置文件

其實對于比較熟悉的開發人員,上一種方式并非推薦用法。用鏈接配置文件將具有更好的靈活性,比如可以指定一個段的對齊方式,存儲位置,某個符號的存儲位置等等。這里同樣為了直觀也做了一個GIF動畫,介紹如何通過鏈接文件進行棧/堆的大小配置。

其最終的效果也一樣如預期將棧區的大小設置好了。

棧溢出

這里為了比較容易的展示棧溢出的問題,在main函數利用遞歸方法計算階乘,代碼如下:

#include 《stdio.h》

#include “main.h”

static uint32_t spSatte[200];

static uint32_t spIndex = 0;

/*為什么要用浮點數,因為數據非常大整型很快就會溢出*/

float factorial(uint32_t n)

uint32_t sp = __get_MSP

/*記錄棧指針的變化情況*/

spSatte[spIndex++] = sp;

if(n==0 || n==1)

return 1;

else

return (float)n*factorial(n-1);

int main(void)

float x = 0;

uint32_t n = 20;

printf(“stack test:

x = factorial(n);

/*打印棧指針變化情況*/

for(int i = 0;i《spIndex;i++)

printf(“MSP-》%08X

spSatte[i]);

/*打印階乘結果*/

printf(“factorial(%d)=%f

n,x);

while (1)

為方便觀察,將stm32f407xx_flash.icf 將棧改為256字節

/*stm32f407xx_flash.icf 將棧改為256字節*/

define symbol __ICFEDIT_size_cstack__ = 0x200;

define symbol __ICFEDIT_size_heap__ = 0x200;

全編譯后通過map文件來看下棧/堆的分配情況:

“P2”, part 3 of 3: 0x400

CSTACK 0x2000‘05d8 0x200 《Block》

CSTACK uninit 0x2000’05d8 0x200 《Block tail》

HEAP 0x2000‘07d8 0x200 《Block》

HEAP uninit 0x2000’07d8 0x200 《Block tail》

- 0x2000‘09d8 0x400

直觀些,翻譯成下圖,CSTACK段分配在0x2000 0280-0x2000 0480,堆分配在0x2000 0480-0x2000 0680。

棧是一種LIFO后入先出的什么數據結構?

圖為什么沒有將0x2000 07D8畫在棧區呢?通過調試發現,這個字空間沒有用做棧的實際存儲。將工程設置成simulation模式,debug進入main.o勾選掉,我們來計算20的階乘,來具體看一下:

棧是一種LIFO后入先出的什么數據結構?

對這個動圖解讀一下:

進入復位是,SP_main為0x200007D8,指向棧底,為空棧。那么這是怎么實現的呢?

__vector_table ;向量表

DCD sfe(CSTACK) ;這條命令會將程序的CSTACK起始地址裝載給SP_main

DCD Reset_Handler ; Reset Handler復位向量

前面說0x200007D8并沒有用到,怎么證明呢,在函數進入mian時,第一次壓棧的情況如下:

棧是一種LIFO后入先出的什么數據結構?

可見STM32棧的增長方向是向下增長的,也即頂在小地址端一側

棧存儲元素是四字節對齊的,因為STM32的字長是字節,如果深入想想,如果不是司字節對齊會怎么樣?留給感興趣的思考一下。

0x200007D8--0x200007DB 這個字存儲單元并不是棧的有效存儲空間。

棧的變化情況:

stack test:

MSP-》200007A8

MSP-》20000790

MSP-》20000778

MSP-》20000760

MSP-》20000748

MSP-》20000730

MSP-》20000718

MSP-》20000700

MSP-》200006E8

MSP-》200006D0

MSP-》200006B8

MSP-》200006A0

MSP-》20000688

MSP-》20000670

MSP-》20000658

MSP-》20000640

MSP-》20000628

MSP-》20000610

MSP-》200005F8

MSP-》200005E0

factorial(20)=2432902023163674771.785700 /*結算結果與用計算器一致*/

每調用一次階乘函數,棧就壓入4個字,由上面還可以看到第20次進入時,棧指針為0x200005E0,如果再壓入4個字棧指針會變成0x200005C8,是這樣嗎,結果還對嗎?將n改為21編譯運行,來看一看:

看到了吧,驚喜來了,棧溢出了,程序已經不聽話了,完全不知道在干嘛了。所以棧溢出的后果是極端危險的,完全無法預期,程序會帶來什么后果。

總結一下

棧是一種LIFO后入先出的數據結構模型,是C/C++程序運行時基礎,沒這個棧,C/C++玩不轉

棧在嵌入式編程領域隨處可見,比如C棧,中斷棧、異常棧、任務棧等等,但其基本工作原理都一樣。支持兩種基本數據操作:壓棧、出棧。

棧溢出程序的結果無法預期,所以合理的設置棧區大小是個永恒的話題,過大則浪費內存,過小則程序會飛。

嵌入式編程遞歸函數要慎用,個人建議不用。比如IEC61508 功能安全標準中強行規定不可使用遞歸函數。

STM32中__get_MSP可以得到當前棧指針的值,據此可以做一定程度的棧溢出保護措施。防止程序跑飛。

通過上面遞歸調用測試,還可以得到一個啟示,嵌入式編程函數嵌套的層級不宜過深,過深則需要相對較大的棧開銷。
責任編輯:pj

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 編譯器
    +關注

    關注

    1

    文章

    1657

    瀏覽量

    49987
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40648
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    程序設計與數據結構

    《程序設計與數據結構》重點闡述了三大方向內容: 1. C語言學習中的痛點:針對當前工程師在C語言學習中的痛點,如指針函數與函數指針,如何靈活應用結構體等。從變量的三要素(變量的類型,變量的值和變量
    發表于 05-13 16:45

    利用結構實現四則運算的巧妙方法

    上個視頻寫了個簡易計算器,算個簡單的加減乘除還行,但是如果來個混合運算,或者加個括號,這幾行代碼就差的太多了。 處理這種混合運算,不得不提到數據結構中的。 我們平時寫的這種表達式,叫做中綴表達式
    的頭像 發表于 02-07 11:06 ?466次閱讀

    hart協議的協議結構分析

    的智能化水平,同時保持與現有模擬系統的兼容性。 2. HART協議概述 HART協議可以分為幾個層次,每個層次負責不同的功能: 2.1 物理層(Physical Layer) 物理層負責在物理媒介上傳輸數據。HART協議使用
    的頭像 發表于 12-02 09:43 ?832次閱讀

    一種面向飛行試驗的數據融合框架

    天地氣動數據一致性,針對某外形飛行試驗數據開展了典型對象的天地氣動數據融合方法研究。結合數據挖掘的隨機森林方法,本文提出了一種面向飛行試驗的
    的頭像 發表于 11-27 11:34 ?777次閱讀
    <b class='flag-5'>一種</b>面向飛行試驗的<b class='flag-5'>數據</b>融合框架

    一種信息引導的量化LLM微調新算法IR-QLoRA

    進行量化+LoRA的路線為例,有研究表明,現有方法會導致量化的LLM嚴重退化,甚至無法從LoRA微調中受益。 為了解決這問題,來自蘇黎世聯邦理工學院、北京航空航天大學和字節跳動的研究人員,最新提出了一種信息引導的量化LLM微
    的頭像 發表于 11-19 17:16 ?749次閱讀
    <b class='flag-5'>一種</b>信息引導的量化<b class='flag-5'>后</b>LLM微調新算法IR-QLoRA

    DDC264配置寄存器數據寫入和320 DCLK時鐘脈沖的回讀數據結構是什么?

    配置寄存器數據寫入和320 DCLK時鐘脈沖的回讀數據結構是什么? 根據注和表9,16位配置寄存器數據,4位修訂ID, 300位校驗模式,怎么可能有1024 TOTAL READ
    發表于 11-19 07:58

    視覺軟件HALCON的數據結構

    在研究機器視覺算法之前,我們需要先了解機器視覺應用中涉及的基本數據結構。Halcon數據結構主要有圖像參數和控制參數兩類參數。圖像參數包括:image、region、XLD,控制參數包括:string、integer、real、handle、tuple數組等。
    的頭像 發表于 11-14 10:20 ?1192次閱讀
    視覺軟件HALCON的<b class='flag-5'>數據結構</b>

    aic3106采數據在經過定轉化,會和matlab中提取的數組致嗎?

    等處理,是否應把sample_data中存放的數轉化為浮點數。另外,如果以往,用matlab進行處理,我讀入個音頻文件,matlab會提取出反映音頻文件幅度特性的數組,那aic3106采數據在經過
    發表于 11-05 07:56

    何為Teable多維表格數據庫,它僅僅是個在線的智能表格嗎?

    維表格是一種創新的數據管理和協作工具,它結合了傳統電子表格的直觀界面與關系數據庫的強大功能。用戶不僅可以像在Excel中樣在二維表格內記錄和編輯
    的頭像 發表于 10-14 16:13 ?1226次閱讀

    嵌入式環形隊列與消息隊列的實現原理

    嵌入式環形隊列,也稱為環形緩沖區或循環隊列,是一種先進先出(FIFO)的數據結構,用于在固定大小的存儲區域中高效地存儲和訪問數據。其主要特點包括固定大小的數組和兩個指針(頭指針和尾指針
    的頭像 發表于 09-02 15:29 ?1154次閱讀

    嵌入式常用數據結構有哪些

    在嵌入式編程中,數據結構的選擇和使用對于程序的性能、內存管理以及開發效率都具有重要影響。嵌入式系統由于資源受限(如處理器速度、內存大小等),因此對數據結構的選擇和使用尤為關鍵。以下是嵌入式編程中常用的幾種數據結構,結合具體特點和
    的頭像 發表于 09-02 15:25 ?982次閱讀

    一種供電總線技術POWERBUS二總線

    根線上完成數據傳輸+供電,尤其適合樓宇里的智能設備聯動控制,如煙霧報警器與報警主機之間,如智能燈光控制等等切合理的應用。 POWERBUS二總線技術,是近些年具備現場驗證的一種二總線技術,感興趣的可以交流 MBUS,RS485
    發表于 07-23 13:38

    鴻蒙語言基礎類庫:ohos.util.ArrayList 線性容器ArrayList

    ArrayList是一種線性數據結構,底層基于數組實現。ArrayList會根據實際需要動態調整容量,每次擴容增加50%。
    的頭像 發表于 07-10 09:37 ?454次閱讀
    鴻蒙語言基礎類庫:ohos.util.ArrayList 線性容器ArrayList

    鴻蒙語言基礎類庫:ohos.util.Deque 線性容器Deque

    Deque(double ended queue)根據循環隊列的數據結構實現,符合先進先出以及先進出的特點,支持兩端的元素插入和移除。Deque會根據實際需要動態調整容量,每次進行兩倍擴容。
    的頭像 發表于 07-10 09:19 ?390次閱讀
    鴻蒙語言基礎類庫:ohos.util.Deque 線性容器Deque

    rup是一種什么模型

    部分)開發的,它基于統建模語言(UML)和面向對象的軟件開發方法。RUP提供了一種結構化的方法來開發軟件,它包括系列的階段、迭代和里程碑,以確保軟件開發過程的順利進行。 RUP的起
    的頭像 發表于 07-09 10:13 ?2550次閱讀
    主站蜘蛛池模板: 奇米777狠狠 | 免费在线播放视频 | 宅男666在线永久免费观看 | 日日干夜夜骑 | 韩国三级中文字幕hd | 亚洲成网站 | 五月婷婷精品 | 四虎国产精品永久地址49 | 欧美色老太婆 | 国产一区二区三区毛片 | 免费人成在线观看视频播放 | 黄色综合 | 成人精品人成网站 | 看天堂 | 日韩a级毛片 | 日本三级成人午夜视频网 | 亚洲国产网址 | 国产精品久久久精品视频 | 亚洲成a人片777777久久 | 高清一区二区三区视频 | 国产精品露脸脏话对白 | 日日夜操| 亚洲国产精品乱码一区二区三区 | 中文字幕亚洲区 | avbobo官网在线入口 | 国产精品美女自在线观看免费 | 欧美女同在线 | 2021国产成人午夜精品 | 男女网站在线观看 | 黄色软件合集 | 男人透女人超爽视频免费 | 爱逼综合| 欧美亚洲一区二区三区在线 | a网站免费 | 日韩卡1卡2卡三卡四卡二卡免 | 亚洲精品网站日本xxxxxxx | 日韩精品亚洲一级在线观看 | 三级毛片在线播放 | 国产综合在线观看视频 | 插菊综合网| 免费视频爱爱 |