国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

常用知識:嵌入式里堆棧原理及其純C實現(xiàn)

發(fā)布時間:2020-4-13 17:24    發(fā)布者:嵌入式人生17
常用知識:嵌入式里堆棧原理及其純C實現(xiàn)
 大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家講的是嵌入式里堆棧原理及其純C實現(xiàn)
  今天給大家分享的這篇還是2016年之前痞子衡寫的技術(shù)文檔,花了點時間重新編排了一下格式。棧這種結(jié)構(gòu)在嵌入式里其實是非常常用的,比如函數(shù)調(diào)用與返回就是典型的棧應(yīng)用,雖然很多時候棧都是CPU系統(tǒng)在自動管理,我們只需要在鏈接文件里分配棧大小以及棧存放位置,但稍微了解一下棧的原理會更加利于我們?nèi)ダ斫馇度胧酱a執(zhí)行機(jī)制,以及幫助我們進(jìn)一步去調(diào)試。
1.何為堆棧?
  堆HEAP與棧STACK是兩個不同概念,其本質(zhì)上都是一種數(shù)據(jù)結(jié)構(gòu)。
  棧是一種按數(shù)據(jù)項排列的數(shù)據(jù)結(jié)構(gòu),只能在一端(棧頂top)對數(shù)據(jù)項進(jìn)行插入和刪除,其符合后進(jìn)先出(Last-In / First-Out)原則。棧(os)一般是由編譯器自動分配釋放,其使用的是一級緩存。
  堆也是一種分配方式類似于鏈表的數(shù)據(jù)結(jié)構(gòu),其可以在任意位置對數(shù)據(jù)項進(jìn)行操作。堆(os)一般由程序員手動分配釋放,其使用的是二級緩存。
  在嵌入式世界里,堆棧一般指的僅是棧。
2.作用與意義
  在MCU中,棧這種結(jié)構(gòu)一般被cpuos所使用。
  在cpu裸機(jī)中使用情況分兩種:一、主動進(jìn)行函數(shù)調(diào)用時,STACK用以暫存下一條指令地址、函數(shù)參數(shù)、函數(shù)中定義的局部變量;二、硬中斷來臨時,暫存當(dāng)前執(zhí)行的現(xiàn)場數(shù)據(jù)(下一條指令地址、各種緩存數(shù)據(jù)),中斷結(jié)束后,用以恢復(fù)。
  在os中使用時,硬棧的使用同cpu裸機(jī);但os一般會為每個任務(wù)額外分配一個軟棧,在任務(wù)調(diào)度時,可用軟中斷打斷當(dāng)前正在執(zhí)行的任務(wù),棧則用以保存各自任務(wù)以恢復(fù)。
3.軟硬之分
  硬件堆棧:是通過寄存器SP作為索引指針的地址,是調(diào)用了BL等函數(shù)調(diào)用指令后硬件自動填充的堆棧。
  軟件堆棧:是編譯器為了處理一些參數(shù)傳遞而做的堆棧,會由編譯器自動產(chǎn)生和處理,可以通過相應(yīng)的編譯選項對其進(jìn)行編輯。
  簡單一點說,硬件堆棧主要做為地址堆棧用,而軟件堆棧主要會被分配成數(shù)據(jù)堆棧。或看其棧頂指針是否和CPU具有特殊的關(guān)聯(lián),有關(guān)聯(lián)者(如SP,而無關(guān)聯(lián)者
4.棧的純C實現(xiàn)
  基本的抽象數(shù)據(jù)類型(ADT)是編寫C程序必要的過程,這類ADT有鏈表、堆棧、隊列和樹等,本節(jié)主要講解下堆棧的幾種實現(xiàn)方法以及他們的優(yōu)缺點。
  堆棧(stack)的顯著特點是后進(jìn)先出(Last-In First-Out, LIFO),其實現(xiàn)的方法有三種可選方案:靜態(tài)數(shù)組、動態(tài)分配的數(shù)組、動態(tài)分配的鏈?zhǔn)浇Y(jié)構(gòu)。
靜態(tài)數(shù)組:特點是要求結(jié)構(gòu)的長度固定,而且長度在編譯時候就得確定。其優(yōu)點是結(jié)構(gòu)簡單,實現(xiàn)起來方便而不容易出錯。而缺點就是不夠靈活以及固定長度不容易控制,適用于知道明確長度的場合。
動態(tài)數(shù)組:特點是長度可以在運(yùn)行時候才確定以及可以更改原來數(shù)組的長度。優(yōu)點是靈活,缺點是由此會增加程序的復(fù)雜性。
鏈?zhǔn)浇Y(jié)構(gòu):特點是無長度上線,需要的時候再申請分配內(nèi)存空間,可最大程度上實現(xiàn)靈活性。缺點是鏈?zhǔn)浇Y(jié)構(gòu)的鏈接字段需要消耗一定的內(nèi)存,在鏈?zhǔn)浇Y(jié)構(gòu)中訪問一個特定元素的效率不如數(shù)組。
  首先先確定一個堆棧接口的頭文件,里面包含了各個方案下的函數(shù)原型,放在一起是為了實現(xiàn)程序的模塊化以及便于修改。然后再接著分別介紹各個方案的具體實施方法。
  堆棧接口stack.h文件代碼:
1./*
2.** 堆棧模塊的接口 stack.h
3.*/  
4.#include  
5.  
6.#define STACK_TYPE int /* 堆棧所存儲的值的數(shù)據(jù)類型 */  
7.  
8./*
9.** 函數(shù)原型:create_stack
10.** 創(chuàng)建堆棧,參數(shù)指定堆棧可以保存多少個元素。
11.** 注意:此函數(shù)只適用于動態(tài)分配數(shù)組形式的堆棧。
12.*/  
13.void create_stack(size_t size);  
14.  
15./*
16.** 函數(shù)原型:destroy_stack
17.** 銷毀一個堆棧,釋放堆棧所適用的內(nèi)存。
18.** 注意:此函數(shù)只適用于動態(tài)分配數(shù)組和鏈?zhǔn)浇Y(jié)構(gòu)的堆棧。
19.*/  
20.void destroy_stack(void);  
21.  
22./*
23.** 函數(shù)原型:push
24.** 將一個新值壓入堆棧中,參數(shù)是被壓入的值。
25.*/  
26.void push(STACK_TYPE value);  
27.  
28./*
29.** 函數(shù)原型:pop
30.** 彈出堆棧中棧頂?shù)囊粋值,并丟棄。
31.*/  
32.void pop(void);  
33.  
34./*
35.** 函數(shù)原型:top
36.** 返回堆棧頂部元素的值,但不改變堆棧結(jié)構(gòu)。
37.*/  
38.STACK_TYPE top(void);  
39.  
40./*
41.** 函數(shù)原型:is_empty
42.** 如果堆棧為空,返回TRUE,否則返回FALSE。
43.*/  
44.int is_empty(void);  
45.  
46./*
47.** 函數(shù)原型:is_full
48.** 如果堆棧為滿,返回TRUE,否則返回FALSE。
49.*/  
50.int is_full(void);  
4.1 靜態(tài)數(shù)組
  在靜態(tài)數(shù)組堆棧中,STACK_SIZE表示堆棧所能存儲的元素的最大值,用top_element作為數(shù)組下標(biāo)來表示堆棧里面的元素,當(dāng)top_element == -1的時候表示堆棧為空;當(dāng)top_element == STACK_SIZE - 1的時候表示堆棧為滿。push的時候top_element1top_element == 0時表示第一個堆棧元素;pop的時候top_element1
  a_stack.c 源代碼如下:
1./*
2.**  
3.** 靜態(tài)數(shù)組實現(xiàn)堆棧程序 a_stack.c ,數(shù)組長度由#define確定
4.*/  
5.  
6.#include"stack.h"  
7.#include  
8.#include  
9.  
10.#define STACK_SIZE 100 /* 堆棧最大容納元素數(shù)量 */  
11.  
12./*
13.** 存儲堆棧中的數(shù)組和一個指向堆棧頂部元素的指針
14.*/  
15.static STACK_TYPE stack[STACK_SIZE];  
16.static int top_element = -1;  
17.  
18./* push */  
19.void push(STACK_TYPE value)  
20.{  
21.    assert(!is_full()); /* 壓入堆棧之前先判斷是否堆棧已滿*/  
22.    top_element += 1;  
23.    stack[top_element] = value;  
24.}  
25.  
26./* pop */  
27.void pop(void)  
28.{  
29.    assert(!is_empty()); /* 彈出堆棧之前先判斷是否堆棧已空 */  
30.    top_element -= 1;  
31.}  
32.  
33./* top */  
34.STACK_TYPE top(void)  
35.{  
36.    assert(!is_empty());  
37.    return stack[top_element];  
38.}  
39.  
40./* is_empty */  
41.int is_empty(void)  
42.{  
43.    return top_element == -1;  
44.}  
45.  
46./* is_full */  
47.int is_full(void)  
48.{  
49.    return top_element == STACK_SIZE - 1;  
50.}  
4.2 動態(tài)數(shù)組
  頭文件還是用stack.h,改動的并不是很多,增加了stack_size變量取代STACK_SIZE來保存堆棧的長度,數(shù)組由一個指針來代替,在全局變量下缺省為0
  create_stack函數(shù)首先檢查堆棧是否已經(jīng)創(chuàng)建,然后才分配所需數(shù)量的內(nèi)存并檢查分配是否成功。destroy_stack函數(shù)首先檢查堆棧是否存在,已經(jīng)釋放內(nèi)存之后把長度和指針變量重新設(shè)置為零。is_empty is_full 函數(shù)中添加了一條斷言,防止任何堆棧函數(shù)在堆棧被創(chuàng)建之前就被調(diào)用。
  d_stack.c源代碼如下:
1./*
2.** 動態(tài)分配數(shù)組實現(xiàn)的堆棧程序 d_stack.c
3.** 堆棧的長度在創(chuàng)建堆棧的函數(shù)被調(diào)用時候給出,該函數(shù)必須在任何其他操作堆棧的函數(shù)被調(diào)用之前條用。
4.*/  
5.#include"stack.h"  
6.#include  
7.#include  
8.#include  
9.  
10./*
11.** 用于存儲堆棧元素的數(shù)組和指向堆棧頂部元素的指針
12.*/  
13.static STACK_TYPE *stack;  
14.static int        stack_size;  
15.static int        top_element = -1;  
16.  
17./* create_stack */  
18.void create_stack(size_t size)  
19.{  
20.    assert(stack_size == 0);  
21.    stack_size = size;  
22.    stack = (STACK_TYPE *)malloc(stack_size * sizeof(STACK_TYPE));  
23.    if(stack == NULL)  
24.        perror("malloc分配失敗");  
25.}  
26.  
27./* destroy */  
28.void destroy_stack(void)  
29.{  
30.    assert(stack_size > 0);  
31.    stack_size = 0;  
32.    free(stack);  
33.    stack = NULL;  
34.}  
35.  
36./* push */  
37.void push(STACK_TYPE value)  
38.{  
39.    assert(!is_full());  
40.    top_element += 1;  
41.    stack[top_element] = value;  
42.}  
43.  
44./* pop */  
45.void pop(void)  
46.{  
47.    assert(!is_empty());  
48.    top_element -= 1;  
49.}  
50.  
51./* top */  
52.STACK_TYPE top(void)  
53.{  
54.    assert(!is_empty());  
55.    return stack[top_element];  
56.}  
57.  
58./* is_empty */  
59.int is_empty(void)  
60.{  
61.    assert(stack_size > 0);  
62.    return top_element == -1;  
63.}  
64.  
65./* is_full */  
66.int is_full(void)  
67.{  
68.    assert(stack_size > 0);  
69.    return top_element == stack_size - 1;  
70.}  
4.3 鏈?zhǔn)浇Y(jié)構(gòu)
  由于只有堆棧頂部元素才可以被訪問,因此適用單鏈表可以很好實現(xiàn)鏈?zhǔn)蕉褩#覠o長度限制。把一個元素壓入堆棧是通過在鏈表頭部添加一個元素實現(xiàn)。彈出一個元素是通過刪除鏈表頭部第一個元素實現(xiàn)。由于沒有長度限制,故不需要create_stack函數(shù),需要destroy_stack進(jìn)行釋放內(nèi)存以避免內(nèi)存泄漏。
  l_stack.c 源代碼如下:
1./*
2.** 單鏈表實現(xiàn)堆棧,沒有長度限制
3.*/  
4.#include"stack.h"  
5.#include  
6.#include  
7.#include  
8.  
9.#define FALSE 0  
10.  
11./*
12.** 定義一個結(jié)構(gòu)以存儲堆棧元素。
13.*/  
14.typedef struct STACK_NODE  
15.{  
16.    STACK_TYPE value;  
17.    struct STACK_NODE *next;  
18.} StackNode;  
19.  
20./* 指向堆棧中第一個節(jié)點的指針 */  
21.static StackNode *stack;  
22.  
23./* create_stack */  
24.void create_stack(size_t size)  
25.{}  
26.  
27./* destroy_stack */  
28.void destroy_stack(void)  
29.{  
30.    while(!is_empty())  
31.        pop();  /* 逐個彈出元素,逐個釋放節(jié)點內(nèi)存 */  
32.}  
33.  
34./* push */  
35.void push(STACK_TYPE value)  
36.{  
37.    StackNode *new_node;  
38.    new_node = (StackNode *)malloc(sizeof(StackNode));  
39.    if(new_node == NULL)  
40.        perror("malloc fail");  
41.    new_node->value = value;  
42.    new_node->next = stack;  /* 新元素插入鏈表頭部 */  
43.    stack = new_node;       /* stack 重新指向鏈表頭部 */  
44.}  
45.  
46./* pop */  
47.void pop(void)  
48.{  
49.    StackNode *first_node;  
50.      
51.    assert(!is_empty());  
52.    first_node = stack;  
53.    stack = first_node->next;  
54.    free(first_node);  
55.}  
56.  
57./* top */  
58.STACK_TYPE top(void)  
59.{  
60.    assert(!is_empty());  
61.    return stack->value;  
62.}  
63.  
64./* is_empty */  
65.int is_empty(void)  
66.{  
67.    return stack == NULL;  
68.}  
69.  
70./* is_full */  
71.int is_full(void)  
72.{  
73.    return FALSE;  
74.}  
  至此,嵌入式里堆棧原理及其純C實現(xiàn)痞子衡便介紹完畢了,掌聲在哪里~~~

本文地址:http://m.qingdxww.cn/thread-584490-1-1.html     【打印本頁】

本站部分文章為轉(zhuǎn)載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀點和對其真實性負(fù)責(zé);文章版權(quán)歸原作者及原出處所有,如涉及作品內(nèi)容、版權(quán)和其它問題,我們將根據(jù)著作權(quán)人的要求,第一時間更正或刪除。
嵌入式人生17 發(fā)表于 2020-4-14 09:21:56
今天的分享就到這里 有疑問3250395686 歡迎和我一起談?wù)?/td>
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區(qū)
  • 利用SAM E54 Xplained Pro評估工具包演示CAN轉(zhuǎn)USB橋接器以及基于CAN的主機(jī)和自舉程序應(yīng)用程序
  • 使用SAM-IoT Wx v2開發(fā)板演示AWS IoT Core應(yīng)用程序
  • 使用Harmony3加速TCP/IP應(yīng)用的開發(fā)培訓(xùn)教程
  • 集成高級模擬外設(shè)的PIC18F-Q71家族介紹培訓(xùn)教程
  • 貿(mào)澤電子(Mouser)專區(qū)
關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久久青草青青亚洲国产免观 | 亚洲男人天| 国产深夜福利19禁在线播放 | 好男人www免费高清视频在线 | 青丝影院高清版在线观看 | 一级爱爱片一级毛片-一毛 一级a爰片久久毛片 | 香蕉久久网站 | 亚洲一区二区三区在线免费观看 | 欧美亚洲一区 | 国产高清精品一级毛片 | 精品国产看高清国产毛片 | 午夜在线成人 | 91九色丨porny丨制服 | 国产免费高清在线精品一区 | 国产精品九九九久久九九 | 四虎成人精品在永久在线观看 | 五月天国产精品 | 亚洲色图在线观看视频 | 欧美在线视频免费 | 国产色婷婷精品综合在线观看 | 国产福利一区二区三区 | 亚洲骚色| 亚洲色图.com | 久久精品国产免费看久久精品 | 国产色婷婷精品综合在线观看 | 韩国日本在线观看 | 男人天堂2022 | 欧美一区2区三区4区公司二百 | 久久6| 一级日本大片免费观看视频 | 黄台| 亚洲视频一区二区三区 | 操网| 日韩不卡高清 | 亚洲综合视频在线观看 | 狠狠88综合久久久久综合网 | 在线不卡日本 | 久久艹艹| 在线a免费观看 | 亚洲国产欧美在线观看 | 日本久久久久中文字幕 |