當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]一、全局變量和局部變量全局變量和局部變量的區(qū)別在于作用域的不同。此外還有靜態(tài)全局變量和靜態(tài)局部變量。全局變量作用域?yàn)槿?,在一個源文件中定義,其他的源文件也可以應(yīng)用。在其他的源文件中使用extern加以聲明

一、全局變量和局部變量

全局變量和局部變量的區(qū)別在于作用域的不同。此外還有靜態(tài)全局變量和靜態(tài)局部變量。

全局變量作用域?yàn)槿?,在一個源文件中定義,其他的源文件也可以應(yīng)用。在其他的源文件中使用extern加以聲明;

靜態(tài)全局變量作用域?yàn)樵撛次募?,只作用在聲明它的源文件中,通過static聲明,這樣即使在其他的源文件中有相同名稱的變量也不相同;

局部變量作用域?yàn)楹瘮?shù)內(nèi)部。當(dāng)函數(shù)被調(diào)用時,為其分配空間,函數(shù)調(diào)用完成后收回內(nèi)存,銷毀變量;

局部靜態(tài)變量作用域?yàn)榫植浚槐怀跏蓟淮?,但是在后面它一直存在。即使函?shù)調(diào)用完成后也一直存在。

全局變量和局部變量都是要分配內(nèi)存的,它們的區(qū)別只是在于作用域不同。

在C中,全局變量、靜態(tài)全局變量及靜態(tài)局部變量都在靜態(tài)存儲區(qū),由于這些變量的生存周期較長,占有較多的內(nèi)存但是由于已經(jīng)分配好了內(nèi)存,因此速度較快,而局部變量則在棧中分配空間。在KeilC51中這是不同的。

二、C51中的全局變量和局部變量

在51中程序ROM和數(shù)據(jù)RAM是嚴(yán)格分開的,特殊功能寄存器與片內(nèi)數(shù)據(jù)存儲器統(tǒng)一編址。這與其他一般的微機(jī)不同。51中內(nèi)部的RAM有256字節(jié),外部可尋址64KB,對于256字節(jié),其中前128字節(jié)(00-7FH)又分為三部分:通用寄存器組、可位尋址區(qū)、用戶RAM區(qū);高128字節(jié)(7F-FF)為SFR。上電復(fù)位后堆棧指針指向07H,在通用寄存器區(qū),此時對戰(zhàn)區(qū)占用1,2,3組寄存器,但是用戶可自行將sp設(shè)置在30-7F。

C51編譯器通過將變量定義為不同的類型,來區(qū)分不同的存儲區(qū),常用的變量類型有:

data:片內(nèi)RAM的低128字節(jié)

bdata:可位尋址的片內(nèi)RAM

以上兩種類型可以快速的存取數(shù)據(jù),常用來放臨時性的傳遞變量或使用頻率較高的變量。

idata:整個片內(nèi)RAM。

xdata:片外存儲區(qū)(64KB),由于在對片外存儲區(qū)操作時,需要先將數(shù)據(jù)移到片內(nèi),進(jìn)行處理后再存儲到片外,因此常用來存放不常用的變量,或收集待處理的數(shù)據(jù),或存放要被發(fā)往另一臺計(jì)算機(jī)的數(shù)據(jù)。

pdata:屬于xdata類型,由于它的高字節(jié)保存在P2口中,只能尋址256字節(jié)。

code:ROM內(nèi),數(shù)據(jù)不會丟失。

此外,C51還有三種存儲模式:SMALL, COMPACT, LARGE

SMALL模式下,如果不做特別說明,參數(shù)及局部變量默認(rèn)為data型,放在片內(nèi)RAM128字節(jié)內(nèi),訪問迅速。由于內(nèi)部的RAM有限,如果變量過多,會導(dǎo)致頻繁的使用寄存器,而使代碼變的冗長。此時棧也在片內(nèi)的RAM,棧長很關(guān)鍵,因?yàn)闂iL依賴于不同函數(shù)的嵌套層數(shù)。

COMPACT:不做特別說明,參數(shù)及局部變量默認(rèn)為pdata,??臻g在內(nèi)部RAM。

LARGE:參數(shù)及局部變量默認(rèn)為xdata,使用DPTR來尋址。訪問效率低,此外這種數(shù)據(jù)指針不能對稱操作。

全局變量會根據(jù)定義的類型或者存儲的模式分配在相應(yīng)的存儲區(qū)內(nèi),有固定的地址,如果全局變量過多則會導(dǎo)致占用太多內(nèi)存,處理速度變慢。

三、共享和覆蓋

由于51的存儲區(qū)有限,因此變有了覆蓋和共享的概念。

共享:有共享變量和共享函數(shù),共享是針對全局變量或靜態(tài)變量而言的,對全局變量定義后就對其分配了內(nèi)存,在任何函數(shù)或者程序中都可以共享該變量的內(nèi)存,在其他的文件中也可以通過聲明extern來實(shí)現(xiàn)共享。共享函數(shù)也是類同。

覆蓋:如果一個程序不再被調(diào)用,也不由其他的程序調(diào)用,在其他的程序運(yùn)行之前程序也不在運(yùn)行,那么這個程序的變量可以放在與其他的程序完全相同的RAM空間,這就是覆蓋。

對于函數(shù)之間的覆蓋在Keil中有一段描述:

The system the linker uses to determine which function arguments (or parameters) and variables may be overlaid is quite sophisticated. It begins when the compiler generates the object code for a function.

The compiler stores all function parameters and local variables in overlayable bit, data, pdata, or xdata segments. The segment names generated by the compiler forParameters and Local Variablesare well-defined. They are used by the compiler to access parameters and local variables.

As the linker resolves references between functions, it builds a call tree based on where those references appear. For instance, iffunction_acallsfunction_b, the compiler inserts a reference tofunction_bin the object code generated forfunction_a. When the linker resolves this reference, it inserts the address offunction_band adds a call fromfunction_atofunction_bin the call tree.

The local variables and parameters offunction_aare overlaid with the variables and parameters offunction_bonly under the following conditions:

No call references of any kind may exist betweenfunction_aandfunction_b. This includes direct calls between A and B as well as calls from other functions on the A branch to B and calls from functions on the B branch to A.

The functions A and B may be invoked by only one program event or root: either the main root or an interrupt but not both. It is impossible to overlay variables and parameters if a function is called by an interrupt and the main program or by two interrupts.

The segment definitions of functions A and B must conform to the rules for segment names described in the compiler manual.

在函數(shù)中定義的動態(tài)局部變量可以被覆蓋,一個函數(shù)說明的變量在下一次進(jìn)入函數(shù)時不同,即函數(shù)調(diào)用時會發(fā)生變化(函數(shù)調(diào)用時才為局部變量分配空間,因此每次調(diào)用分配的地址可能不同)。有一些編譯器通常把局部變量放在堆棧上,這樣運(yùn)行起來位置不固定,棧操作不方便,而在51的編譯器中則監(jiān)視函數(shù)調(diào)用的嵌套順序,把幾個函數(shù)的變量放在同樣固定的位置。在51編譯器中連接器會搜索所有函數(shù)中局部變量占用存儲區(qū)間最多的函數(shù),然后已這個函數(shù)的局部變量的占用的空間的多少開辟一片空間,其他函數(shù)的局部變量也放在該空間中,同時實(shí)現(xiàn)了變量的覆蓋(無相互調(diào)用)與地址的共享。例如函數(shù)A占10個字節(jié),函數(shù)B占20個字節(jié),函數(shù)C占15個字節(jié),如果它們之間沒有相互調(diào)用則僅需20個字節(jié)就可以滿足45個字節(jié)的變量需要。

C51中根據(jù)變量定義是的數(shù)據(jù)類型在相應(yīng)的存儲區(qū)內(nèi)為變量分配內(nèi)存,在內(nèi)部整個RAM區(qū)中,先為定義在該端的全局變量分配地址,然后是程序中所有函數(shù)的參數(shù)和局部變量的覆蓋區(qū)(內(nèi)部RAM存取迅速)。以上兩部分內(nèi)存都是上面所說的C中的靜態(tài)存儲區(qū)(段)。接下來就是系統(tǒng)的堆棧,棧底有?STACK自動生成,棧頂在0xFF。

正是由于所有函數(shù)的參數(shù)和局部變量的共享一個覆蓋區(qū),函數(shù)沒有相互的調(diào)用時,在執(zhí)行一個函數(shù)時,會將另一個函數(shù)的變量的存儲區(qū)覆蓋。如果函數(shù)有調(diào)用,那么不會覆蓋原來函數(shù)的局部變量的區(qū)間,但如果函數(shù)的嵌套(遞歸)層數(shù)太多,所有的變量的內(nèi)存大于了覆蓋區(qū)時,一個函數(shù)的內(nèi)部的變量可能會被新調(diào)用的函數(shù)沖掉,再返回該函數(shù)時,無法找到相應(yīng)變量的內(nèi)存,也就無法找到該變量的值。通過聲明為可重入函數(shù),讓參數(shù)和變量放在堆棧中。

對于覆蓋,大多人認(rèn)為是為了節(jié)省內(nèi)存,但網(wǎng)上有另一種說法,個人覺得很有道理,引用如下:

一般的C編譯器(或者更確切點(diǎn)地說:基于一般的處理器上的C編譯器),其函數(shù)的局部變量是存放于堆棧中的,而C51是存放于一個可覆蓋的(數(shù)據(jù))段中的.

  至于C51這樣做的原因,不是象有些人說的那樣,為了節(jié)約內(nèi)存.事實(shí)上,這樣做根本節(jié)約不了內(nèi)存.理由如下:

  1) 如果一個函數(shù)func1調(diào)用另一個函數(shù)func2,那么func1,func2的局部變量根本就不能是同一塊內(nèi)存.C51還是要為他們分配不同的RAM.這跟使用堆棧相比,節(jié)約不了內(nèi)存.

  2) 如果func1,func2不是在一個調(diào)用鏈上,那么C51可以通過覆蓋分析,讓它們的局部變量共享相同的內(nèi)存地址.但這樣也不會比使用堆棧節(jié)約內(nèi)存.因?yàn)榧热凰鼈兪窃诓煌恼{(diào)用鏈上,那么當(dāng)其中一個函數(shù)運(yùn)行時,那么另外一個函數(shù)必然不在其生命期內(nèi),它所占用的堆棧也已釋放,歸還給系統(tǒng).

  真實(shí)的原因(C51使用覆蓋段作為局部變量的存放地的原因)是:

  51的指令系統(tǒng)沒有一個有效的相對尋址(變址尋址)的指令,這使得使用堆棧作為變量的代價太過昂貴.

  使用堆棧存放變量的一般做法是:

  進(jìn)入函數(shù)時,保留一段堆??臻g,作為變量的存放空間,用一個可作為基址尋址的寄存器指向這個空間,通過加上一個偏移量,就可以訪問不同的變量了.

  例如: MOV EAX, [EBP + 14];X86指令

  LDR R0, [R12, #14];ARM指令

  都可以很好的解決這個問題.

  但51缺少這樣的指令.

  *其實(shí),51中還是有2個可變址尋址的指令的,但不適合訪問堆棧的局部變量這樣的場合.

  MOVC A, @A+DPTR

  MOVC A, @A+PC

  所以,C51有個特別的關(guān)鍵字: reentrant 用來解決函數(shù)重入的問題。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉