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

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

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

3天內不再提示

全局數據區和棧區是誰在幕后分配的?怎么分配的?

痞子衡嵌入式 ? 來源:技術讓夢想更偉大 ? 2023-04-06 09:51 ? 次閱讀

何為變量?

變量一般可以細分為如下圖:

fbfdb950-d40b-11ed-bfe3-dac502259ad0.png

本節重點為了讓大家理解內存模型的“?!保瑫簳r不考慮“靜態變量” 的情況,并約定如下:

“全局變量”僅僅默認為“普通全局變量”;

“局部變量”僅僅默認為“普通局部變量”。

如何判定全局變量和局部變量?

簡單直觀的來說,全局變量就是在函數外面定義的變量,局部變量就是在函數內部定義的變量,下面的例子能很清晰地說明全局變量和局部變量的判定方法:

unsigned char a;//在函數外面定義的,所以是全局變量。
voidmain()//主函數
{
 unsigned char b;//在函數內部定義的,所以是局部變量。
b=a;
while(1)
{

}
}

全局變量和局部變量的內存模型

單片機內存包括ROMRAM兩部分,ROM存儲的是單片機程序中的指令和一些不可更改的常量數據,而RAM存放的是可以被更改的變量數據;

也就是說,全局變量和局部變量都是存放在RAM,但是,雖然都是存放在RAM,全局變量和局部變量之間的內存模型還是有明顯的區別的。

因此,分了兩個不同的RAM區,全局變量占用的RAM區稱為全局數據區, 局部變量占用的RAM區稱為。

它們的內存模型到底有什么本質的區別呢?

全局數據區就像你自己家的房間,是唯一的,一個房間的地址只能你一個人?。僭O你還是單身狗的時候),而且是永久的(sorry),所以說每個全局變量都有唯一對應的 RAM 地址, 不可能重復的。

就像客棧, 一年下來每天晚上住的人不一樣,每個人在里面居住的時間是有期限的,不是長久的,一個房間的地址一年下來每天可能住進不同的人,不是唯一的。

全局數據區的全局變量擁有永久產權,區的局部變量只能臨時居住在賓館客棧, 地址不是唯一的, 有期限的。

是給程序里所有函數內部的局部變量共用的,函數被調用的時候,該函數內部的每個局部變量就會被分配對應到的某個RAM地址,函數調用結束后,該局部變量就失效。

因此它對應的的RAM空間就被收回,以便給下一個被調用的函數的局部變量占用。

舉例借用“賓館客棧”來比喻局部變量所在的“棧”。

voidfunction(void);//子函數的聲明

voidfunction(void)//子函數的定義
{
unsignedchara;//局部變量
a=1;
}

voidmain()//主函數
{
function();//子函數的調用
}

我們看到單片機從主函數 main 往下執行, 首先遇到function()子函數的調用, 所以就跳到function()函數的定義那里開始執行, 此時的局部變量 a 開始被分配在RAM的“棧區” 的某個地址, 相當于你入住賓館被分配到某個房間。

單片機執行完子函數function()后,局部變量 a 在RAM的棧區所分配的地址被收回, 局部變量a 消失,被收回的RAM地址可能會被系統重新分配給其它被調用的函數的局部變量。

此時相當于你離開賓館,從此你跟那個賓館的房間沒有啥關系, 你原來在賓館入住的那個房間會被賓館老板重新分配給其他的客人入住。

全局變量的作用域是永久性不受范圍限制的,而局部變量的作用域就是它所在函數的內部范圍。全局變量的全局數據區是永久的私人房子,局部變量的棧是臨時居住的客棧。

總結如下

每定義一個新的全局變量,就意味著多開銷一個新的RAM內存。而每定義一個局部變量,只要在函數內部所定義的局部變量總數不超過單片機的棧區,此時的局部變量不開銷新的RAM內存, 因為局部變量是臨時借用棧的, 使用后就還給棧,棧是公共區, 可以重復利用,可以服務若干個不同的函數內部的局部變量。

單片機每次進入執行函數時,局部變量都會被初始化改變,而全局變量則不會被初始化, 全局變量是一直保存之前最后一次更改的值。

有哪些常見疑問?

全局數據區棧區是誰在幕后分配的, 怎么分配的?

是C編譯器自動分配的, 至于怎么分配,誰分配多一點,誰分配少一點,C 編譯器會有一個默認的比例分配, 我們一般都不用管。

棧區是臨時借用的,子函數被調用的時候,它內部的局部變量才會“臨時” 被分配到“?!?區的某個地址,那么問題來了,誰在幕后主持“棧區” 這些分配的工作?

單片機已經上電開始運行程序的時候,編譯器已經不起作用,“棧區” 分配給函數內部局部變量的工作,確實是 C 編譯器做的,但這是在單片機上電前。

C 編譯器就把所有函數內部的局部變量的分配工作就規劃好了,都指定了如果某個函數一旦被調用,該函數內部的哪個局部變量應該分到“棧區” 的哪個地址,C 編譯器都是事先把這些“后事” 都交代完畢了才結束自己的生命。

等單片機上電開始工作的時候,雖然C編譯器此時不在了,但是單片機都是嚴格按照C編譯器交代的遺囑開始工作和分配“棧區”的。因此,“棧區” 的“臨時分配” 非真正嚴格意義上的“臨時分配”。

函數內部所定義的局部變量總數不超過單片機的“?!?區的 RAM 數量, 那, 萬一超過了“?!?區的 RAM數量, 后果嚴重嗎?

這種情況專業術語叫爆棧。程序會出現莫名其妙的異常,后果特別嚴重。

為了避免這種情況, 一般在編寫程序的時候, 函數內部都不能定義大數組的局部變量, 局部變量的數量不能定義太多太大,尤其要避免剛才所說的定義開辟大數組局部變量這種情況。

大數組的定義應該定義成全局變量,或者定義成靜態的局部變量。

有一些C編譯器,遇到“爆?!?的情況,會好心跟你提醒讓你編譯不過去,但是也有一些 C 編譯器可能就不會給你提醒,所以大家以后做項目寫函數的時候,要對爆棧心存敬畏。

全局變量和局部變量的優先級

剛才說到,全局變量的作用域是永久性并且不受范圍限制的,而局部變量的作用域就是它所在函數的內部范圍。

那么問題來了,假如局部變量和全局變量的名字重名了,此時函數內部執行的變量到底是局部變量還是全局變量?

這個問題就涉及到優先級。

注意,當面對同名的局部變量和全局變量時,函數內部執行的變量是局部變量,也就是局部變量在函數內部要比全局變量的優先級高。

我們來舉一些例子

請看下面第一個例子

unsignedchara=5;//此處第1個a是全局變量

voidmain()//主函數
{
unsignedchara=2;//此處第2個a是局部變量,跟上面全局變量的第1個a重名了
print(a);//把a發送到電腦端的串口助手軟件上觀察
while(1)
{

}
}

正確的答案是 2。在函數內部的局部變量比全局變量的優先級更加高。

雖然這里的兩個a重名了, 但是它們的內存模型不一樣,第1個全局變量的a是分配在全局數據區,是具有唯一的地址的,而第2個局部變量的a是被分配在臨時的棧區的,寄生在 main 函數內部。

再看下面第二個例子

voidfunction(void);//函數聲明
unsignedchara=5;//此處第1個a是全局變量

voidfunction(void)//函數定義
{
 unsigned char a=3;//此處第 2 個 a 是局部變量。
}

voidmain()//主函數
{
 unsigned char a=2;//此處第 3 個 a 也是局部變量。
function();//子函數被調用
print(a);//把 a 發送到電腦端的串口助手軟件上觀察。
while(1)
{
}
}

正確的答案是2。因為,function這個子函數是被調用結束之后,才執行 print(a)的, 就意味函數內部的局部變量(第2個局部變量 a)是在執行 print(a)語句的時候就消亡不存在了, 所以此時print(a)的a是第3個局部變量的a(在 main 函數內部定義的局部變量的 a)。

再看下面第三個例子

voidfunction(void);//函數聲明
unsignedchara=5;//此處第1個a是全局變量

voidfunction(void)//函數定義
{
unsignedchara=3;//此處第2個a是局部變量
}

voidmain()//主函數
{
function();//子函數被調用
print(a);//把a發送到電腦端的串口助手軟件上觀察
while(1)
{
}
}

正確的答案是5。因為function這個子函數是被調用結束之后,才執行print(a)的,就意味function函數內部的局部變量(第2個局部變量)是在執行function(a)語句的時候就消亡不存在了。

同時,因為此時main函數內部也沒有定義a的局部變量,所以此時function(a)的a是必然只能是第1個全局變量的a(在main函數外面定義的全局變量的a)。






審核編輯:劉清

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

    關注

    6040

    文章

    44592

    瀏覽量

    636864
  • ROM
    ROM
    +關注

    關注

    4

    文章

    575

    瀏覽量

    85862
  • RAM
    RAM
    +關注

    關注

    8

    文章

    1369

    瀏覽量

    114814
  • 嵌入式編程
    +關注

    關注

    0

    文章

    27

    瀏覽量

    10338

原文標題:從嵌入式編程中感悟「?!篂楹畏缴袷??

文章出處:【微信號:pzh_mcu,微信公眾號:痞子衡嵌入式】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    應大家要求詳細講解下C語言內存分配-通俗理解

    一次,如果反復,則需使用跳轉指令,如果進行遞歸,則需借助來實現。代碼包括操作碼和要操作的對象(或對象的地址引用),如果是立即數(即具體的數值,如2),將直接包含在代碼中;如果是局部數據,將在
    發表于 10-08 14:13

    C語言內存分配-通俗理解

    一次,如果反復,則需使用跳轉指令,如果進行遞歸,則需借助來實現。代碼包括操作碼和要操作的對象(或對象的地址引用),如果是立即數(即具體的數值,如2),將直接包含在代碼中;如果是局部數據,將在
    發表于 10-08 14:57

    請問stm32和堆的如何設置大小

    里邊的設置的大小?,F在的問題是我把和堆區分配的大小已經加大了過一段時間還是死機,那么
    發表于 12-17 08:48

    keilC51編譯器在內存分配時知道避開模擬嗎?

    程序中用了很多重入函數,假如程序中內存占用2K,我把模擬放在1K的位置,會不會出問題?編譯器在內存分配的時候知不知道避開模擬呢?
    發表于 04-08 09:34

    全局變量數組分配分太多怎么辦

    如果全局數組分配的太多太大會不會 跟 子函數里的數組有交集現象啊,我知道我的問題很白癡,一個在全局數據段 一個在里,位置都不一樣,但是 通過運行后的
    發表于 05-29 04:35

    全局數組和全局變量之類的數據結構會對RTOS帶來什么樣的影響?

    最近在將一個協議移植到FreeRTOS系統上。之前的協議是基于前后臺系統開發的,在串口接收中斷將接收到的數據寫入一個環形緩存,再根據協議從這個緩存
    發表于 06-13 09:00

    freertos與STM32如何分配堆棧空間

    freertos與STM32分析、堆、全局、常量、代碼、RAM、ROM,及如何分配堆???/div>
    發表于 08-03 06:36

    stm32的代碼和常量的地址分配在哪

    stm32的代碼和常量的地址分配在哪?stm32的全局變量和堆棧的地址又分配在哪?
    發表于 12-02 06:05

    如何對RAM空間分配操作

    在代碼編譯過程中,編譯器會根據配置和代碼進行空間分配,包括對內存RAM的空間分配,對RAM空間分配操作,可以理解如下:分配全局變量區
    發表于 01-20 08:05

    談一談單片機程序的與堆

    一、程序內存分配由c/C++編譯的程序占用的內存分為以下幾個部分1、(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于
    發表于 02-28 07:35

    內存分配的三種情況解析:靜態、、堆

    (1)靜態存儲: 主要存放static靜態變量、全局變量、常量 。這些數據內存在編譯的時候就已經為他們分配好了內存,生命周期是整個程序從運行到結束。 (2)
    發表于 12-15 11:26 ?2150次閱讀

    C語言堆棧程序內存的分配

    。 堆(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒
    的頭像 發表于 10-21 14:51 ?2345次閱讀

    對于51單片機的RAM內存分配(包含分配

    的常規寄存器和一字節的空間(一字節的空間是在啟動文件里暫時分配的)程序里定義的全局變量會放在靜態存儲,局部變量、形參、嵌套函數地址和字
    發表于 11-20 12:51 ?10次下載
    對于51單片機的RAM內存<b class='flag-5'>分配</b>(包含<b class='flag-5'>棧</b>的<b class='flag-5'>分配</b>)

    C語言怎么建立內存的動態分配

    在C語言中,全局變量是分配在內存中的靜態存儲的,非靜態的局部變量,包括形參是分配在內存中的動態存儲的,這個存儲
    的頭像 發表于 03-10 15:30 ?866次閱讀

    全局數據包通信簡介

    1?全局數據包通信簡介 對于PLC之間的數據交換,只關心數據的發送和接收,全局數據包的通信方
    的頭像 發表于 05-29 10:04 ?896次閱讀
    <b class='flag-5'>全局數據</b>包通信簡介
    主站蜘蛛池模板: 亚洲精品视频在线| 深爱激情五月网| 黄色大毛片| 日本三级吹潮| 四虎永久在线精品国产免费 | 鲁一鲁色一色| 如果我们是季节韩剧在线观看| 国产视频第一页| 中文字幕一二三区| www激情五月| 国产小视频在线免费| 色综合色综合色综合色综合网| 97久久综合九色综合| 成人小视频在线| 国产在线精彩视频二区| 欧美日韩高清一区| 日韩高清特级特黄毛片| 色精品一区二区三区| 色综合天天综合网国产国产人 | 亚洲免费成人| 日本一区不卡视频| 91免费在线视频| 中文字幕 亚洲一区| 禁漫羞羞a漫入口| 国产盗摄女厕美女嘘嘘| 性视频在线| 婷婷激情小说| 婷婷狠狠| 毛片网子| 天天看天天操| 日韩成人免费观看| 影院在线观看免费| tube4欧美最新69| 伊人9| 天堂资源中文在线| 色多多在线观看视频| 久久三级国产| 国产你懂的在线| aaaa大片| 狠狠干网| 免费我看视频在线观看|