C语言(记录)——内存相关_2:内存的编址与管理
本文是基于嵌入式的C語(yǔ)言
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
內(nèi)存編址方法
內(nèi)存在邏輯上就是一個(gè)一個(gè)的格子,這些格子可以用來(lái)裝東西(里面裝的東西就是內(nèi)存中存儲(chǔ)的數(shù)),每個(gè)格子有一個(gè)編號(hào),這個(gè)編號(hào)就是內(nèi)存地址,這個(gè)內(nèi)存地址(一個(gè)數(shù)字)和這個(gè)格子的空間(實(shí)質(zhì)是一個(gè)空間)是一一對(duì)應(yīng)且永久綁定的。這就是內(nèi)存的編址方法。
在程序運(yùn)行時(shí),計(jì)算機(jī)中CPU實(shí)際只認(rèn)識(shí)內(nèi)存地址,而不關(guān)心這個(gè)地址所代表的空間在哪里,怎么分布這些實(shí)體問(wèn)題。因?yàn)橛布O(shè)計(jì)保證了按照這個(gè)地址就一定能找到這個(gè)格子,所以說(shuō)內(nèi)存單元的2個(gè)概念:地址和空間是內(nèi)存單元的兩個(gè)方面。
內(nèi)存和數(shù)據(jù)類型的關(guān)系
C語(yǔ)言中的基本數(shù)據(jù)類型有:char short int long float double
int 整形(整數(shù)類型,這個(gè)整就體現(xiàn)在它和CPU本身的數(shù)據(jù)位寬是一樣的)譬如32位的CPU,整形就是32位,int就是32位。
數(shù)據(jù)類型和內(nèi)存的關(guān)系就在于:
數(shù)據(jù)類型是用來(lái)定義變量的,而這些變量需要存儲(chǔ)、運(yùn)算在內(nèi)存中。所以數(shù)據(jù)類型必須和內(nèi)存相匹配才能獲得最好的性能,否則可能不工作或者效率低下。
比如:在32位系統(tǒng)中定義變量最好用int,因?yàn)檫@樣效率高。原因就在于32位的系統(tǒng)本身配合內(nèi)存等也是32位,這樣的硬件配置天生適合定義32位的int類型變量,效率最高。也能定義8位的char類型變量或者16位的short類型變量,但是實(shí)際上訪問(wèn)效率不高。
再如:在很多32位環(huán)境下,我們實(shí)際定義bool類型變量(實(shí)際只需要1個(gè)bit就夠了)都是用int來(lái)實(shí)現(xiàn)bool的。也就是說(shuō)我們定義一個(gè)bool b1;時(shí),編譯器實(shí)際幫我們分配了32位的內(nèi)存來(lái)存儲(chǔ)這個(gè)bool變量b1。編譯器這么做實(shí)際上浪費(fèi)了31位的內(nèi)存,但是好處是效率高。
內(nèi)存管理
說(shuō)到內(nèi)存管理就要說(shuō)到數(shù)據(jù)結(jié)構(gòu)和堆。
最簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)——數(shù)組。當(dāng)程序中有許多相同類型的數(shù)據(jù)需要同意管理時(shí),單個(gè)的變量會(huì)顯得比較臃腫和雜亂,這時(shí)候就需要數(shù)組來(lái)有效管理數(shù)據(jù),也就是對(duì)應(yīng)于內(nèi)存。但很明顯數(shù)組的優(yōu)缺點(diǎn)從其使用特性中顯露無(wú)遺。?優(yōu)勢(shì):數(shù)組比較簡(jiǎn)單,訪問(wèn)用下標(biāo),可以隨機(jī)訪問(wèn)。缺陷:1 數(shù)組中所有元素類型必須相同;2 數(shù)組大小必須定義時(shí)給出,而且一旦確定不能再改。針對(duì)數(shù)組的優(yōu)缺點(diǎn),結(jié)構(gòu)體便隆重登場(chǎng)。
結(jié)構(gòu)體。在管理一個(gè)或幾個(gè)事物的不同屬性,在數(shù)據(jù)上體現(xiàn)為不同的變量,這時(shí),數(shù)組就會(huì)說(shuō)“老子干不了”。結(jié)構(gòu)體就是為了此種情況而生。比如,需要管理學(xué)生信息,就可以創(chuàng)建如下結(jié)構(gòu)體,以便統(tǒng)一整齊管理。
struct student
{
unsigned int age;?????????
char name[20];
}
棧是一種數(shù)據(jù)結(jié)構(gòu),C語(yǔ)言中使用棧來(lái)保存局部變量。棧是被發(fā)明出來(lái)管理內(nèi)存的。其管理內(nèi)存的特點(diǎn)是小內(nèi)存、自動(dòng)化。
C語(yǔ)言中的局部變量是用棧來(lái)實(shí)現(xiàn)的。
我們?cè)贑中定義一個(gè)局部變量時(shí)(int num),編譯器會(huì)在棧中分配一段空間(4字節(jié))給這個(gè)局部變量用(分配時(shí)棧頂指針會(huì)移動(dòng)給出空間,給局部變量a用的意思就是,將這4字節(jié)的棧內(nèi)存的內(nèi)存地址和我們定義的局部變量名a給關(guān)聯(lián)起來(lái)),對(duì)應(yīng)棧的操作是入棧。
注意:這里棧指針的移動(dòng)和內(nèi)存分配是自動(dòng)的(棧自己完成,不用我們寫代碼去操作)。
然后等我們函數(shù)退出的時(shí)候,局部變量要滅亡。對(duì)應(yīng)棧的操作是彈棧(出棧)。出棧時(shí)也是棧頂指針移動(dòng)將棧空間中與a關(guān)聯(lián)的那4個(gè)字節(jié)空間釋放。這個(gè)動(dòng)作也是自動(dòng)的,也不用人寫代碼干預(yù)。棧的小內(nèi)存特點(diǎn)可以說(shuō)是其的缺點(diǎn),所以所以我們?cè)贑語(yǔ)言中定義局部變量時(shí)不能定義太多或者太大(譬如不能定義局部變量時(shí) int a[10000];)。
堆(heap)是一種內(nèi)存管理方式。內(nèi)存管理對(duì)操作系統(tǒng)來(lái)說(shuō)是一件非常復(fù)雜的事情,因?yàn)槭紫葍?nèi)存容量很大,其次內(nèi)存需求在時(shí)間和大小塊上沒(méi)有規(guī)律(操作系統(tǒng)上運(yùn)行著的幾十、幾百、幾千個(gè)進(jìn)程隨時(shí)都會(huì)申請(qǐng)或者釋放內(nèi)存,申請(qǐng)或者釋放的內(nèi)存塊大小隨意)。
堆這種內(nèi)存管理方式特點(diǎn)就是自由(隨時(shí)申請(qǐng)、釋放;大小塊隨意)。堆內(nèi)存是操作系統(tǒng)劃歸給堆管理器(操作系統(tǒng)中的一段代碼,屬于操作系統(tǒng)的內(nèi)存管理單元)來(lái)管理的,然后向使用者(用戶進(jìn)程)提供API(malloc和free)來(lái)使用堆內(nèi)存。
我們什么時(shí)候使用堆內(nèi)存?需要內(nèi)存容量比較大時(shí),需要反復(fù)使用及釋放時(shí),很多數(shù)據(jù)結(jié)構(gòu)(譬如鏈表)的實(shí)現(xiàn)都要使用堆內(nèi)存。
堆管理內(nèi)存的特點(diǎn)(大塊內(nèi)存、手工分配&使用&釋放)
1:容量不限(常規(guī)使用的需求容量都能滿足)。
2:申請(qǐng)及釋放都需要手工進(jìn)行,手工進(jìn)行的含義就是需要程序員寫代碼明確進(jìn)行申請(qǐng)malloc及釋放free。如果程序員申請(qǐng)內(nèi)存并使用后未釋放,這段內(nèi)存就丟失了(在堆管理器的記錄中,這段內(nèi)存仍然屬于你這個(gè)進(jìn)程,但是進(jìn)程自己又以為這段內(nèi)存已經(jīng)不用了,再用的時(shí)候又會(huì)去申請(qǐng)新的內(nèi)存塊,這就叫吃內(nèi)存),稱為內(nèi)存泄漏。
轉(zhuǎn)載于:https://www.cnblogs.com/printf631/p/7765878.html
總結(jié)
以上是生活随笔為你收集整理的C语言(记录)——内存相关_2:内存的编址与管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用SSIS Slow Changing
- 下一篇: 在windows命令行中查询MySQL乱