最近很多同學希望了解c語言的記憶體分配,雖然可以在網際網路上找到諸多的講解,但是你會發現要麼不通俗易懂,要麼不算太全面。而這些對於新手而言,又絕對會把你弄得暈頭轉向的,所以在此對網上和書本上的諸般講解,進行了通俗的翻譯和總結。
在說記憶體分配之前,先提一點題外話,因為在和同學們講解記憶體分配的時候,他們不是很明白為什麼要進行這樣的分配。所以先講解下,計算機的組成和基本原理。
一、計算機的組成
計算機的五大組成部分:運算器、控制器、儲存器、輸入裝置和輸出裝置。
我們都知道計算機的處理中心是cpu,它主要由運算器和控制器組成。
1) 運算器
實現算術運算和邏輯運算的部分,主要對資料進行加工處理。
2) 控制器
計算機的指揮中心,它通過位址訪問儲存器,從儲存器中取出指令(程式),並指出下一指令在儲存器中的位置,將取出的指令經指令暫存器送往指令解碼器,經過對指令的分析產生相應的操作,控制其他部件的有條不紊的工作。
3)儲存器
計算機存放所有資料和程式的記憶部分,它分為兩大類:一類是內部儲存器(記憶體),一類是外部儲存器(外存)。儲存器由若干個儲存單元組成,每個儲存單元都有乙個位址,計算機通過位址對儲存單元進行讀寫。
4) 輸入裝置
向計算機輸入資訊(程式、資料、聲音、文字、圖形、影象等)的裝置(鍵盤、滑鼠、圖形掃瞄器、觸控螢幕、條形碼輸入器、光筆等)。
5) 輸出裝置
主要有顯示器、印表機和繪圖儀等。
二、記憶體分配
在任何程式設計環境及語言中,記憶體管理都十分重要。在目前的計算機系統或嵌入式系統中,記憶體資源仍然是有限的。因此在程式設計中,有效地管理記憶體資源是程式設計師首先考慮的問題
1) c程式結構:可執行**儲存時
下面是c語言可執行程式的基本情況:
上面分別是:**區、全域性初始化資料區/靜態資料區、未初始化資料區、十進位制總和、十六進製制總和、檔名。
我們可以看出程式在未執行前,沒有調入到記憶體時,分為三個部分:**區(text)、資料區(data)、未初始化資料區(bss)。
(1) **區(text)
存放cpu可執行的機器指令,由於程式被經常使用,防止其被意外修改,**區通常是唯讀的。
(2) 全域性初始化資料區/靜態資料區(data)
存放被初始化的全域性變數、靜態變數(全域性靜態變數和區域性靜態變數)、常量資料(如字串常量)。
(3) 未初始化資料區(bss)
存放未初始化的全域性變數,bss這個叫法是根據早期的彙編運算子而來的,這個彙編運算子標誌著乙個塊的開始。bss區的資料在程式開始執行之前被核心初始化為0或空指標(null)。
2)c程式結構:程式執行時
乙個正在執行的c程式,占用的記憶體分為5個區域:**區、初始化資料區/靜態資料區、未初始化資料區、堆區、棧區。
(1) **區(text)
**區指令根據程式設計流程依次執行,對於順序指令,則只會執行一次,如果反覆,則需使用跳轉指令,如果進行遞迴,則需借助棧來實現。
**區包括操作碼和要操作的物件(或物件的位址引用),如果是立即數(即具體的數值,如2),將直接包含在**中;如果是區域性資料,將在棧中分配空間,然後引用該資料的位址;如果是bss區和資料區,在**中同樣引用該資料的位址。
(2) 全域性初始化資料區/靜態資料區(data)
只初始化一次。上面已經說過,在程式編譯時,該區域已經被分配好了,這塊內存在程式的整個執行期間都存在,當程式結束時,才會被釋放。
(3)未初始化資料 區(bss)
在執行時改變其值。
(4)棧區(stack)
存放函式的引數值和區域性變數,由編譯器自動分配釋放,其操作方式類似於資料結構的棧。其特點是不需要程式設計師去考慮記憶體管理的問題,很方便;同時棧的容量很有限,在linux系統中,棧的容量只有8m,並且當相應的範圍結束時(如函式),區域性變數就不能再使用。
(5)堆區(heap)
有些操作物件只有在程式執行時才能確定,這樣編譯器在編譯時就無法為他們預先分配空間,只有程式執行時才分配,這就是動態記憶體分配。堆區就是用於動態記憶體分配(如malloc的動態記憶體分配),堆在記憶體中位於bss區和棧區之間,一般由程式設計師申請和釋放。
之所以分配如此多的區域,主要是因為:
乙個程序在執行時,**是根據流程依次執行的,**只需訪問一次,當然跳轉或遞迴時**會被執行多次,而資料一般都需要訪問多次,因此單獨開闢空間以便訪問和節約空間。
下面是乙個詳細的**,來全面分析記憶體分配情況:
int a = 0; //a在全域性初始化資料區
char *p1; //p1在bss區(未初始化全域性變數)
static int c = 0; //c在全域性初始化資料區(c是全域性靜態變數)
struct employee
char name[20];
int age;
float score;
}e1; //e1在全域性初始化資料區
int main()
int b; //b在棧區(區域性變數)
char s = 「abc」; //s在棧區,「abc」在常量區(全域性初始化資料區)
char *p2; //p2在棧區
char *p3 = 「123456」; //p3在棧區,「123456」在常量區(全域性初始化資料區)
static int d = 0; //d在全域性初始化資料區(靜態區域性變數)
struct student
char *name; //name在棧區,name指標指向是在堆區
int age;
float score;
}s1; //s1在棧區
p1 = (char*)malloc(10); //分配得來的10個位元組的區域在堆區
p2 = (char*)malloc(20); //分配得來的20個位元組的區域在堆區
name = (cahr *)malloc(20); //分配得來的20個位元組的區域在堆區
/*從常量區的「hello world」字串複製到剛分配到的堆區*/
strcpy(p1, 「hello world」);
free(p1); //釋放記憶體
free(p2); //釋放記憶體
文章選自華清遠見嵌入式培訓
>>>更多優秀技術博文每日更新
C語言記憶體分配
c語言的記憶體分配主要有5個區域 1 棧區 在執行函式時,函式內的區域性變數 不包括static變數 函式返回值的儲存單元在棧區上建立。函式執行結束時這些儲存單元自動被釋放。棧區記憶體分配運算內置於處理器的指令集中,效率很高,但分配的記憶體容量有限。2 堆區 程式在執行的時候用malloc call...
C語言記憶體分配
c語言的記憶體分配主要有5個區域 1 棧區 在執行函式時,函式內的區域性變數 不包括static變數 函式返回值的儲存單元在棧區上建立。函式執行結束時這些儲存單元自動被釋放。棧區記憶體分配運算內置於處理器的指令集中,效率很高,但分配的記憶體容量有限。2 堆區 程式在執行的時候用malloc call...
C語言記憶體分配
objective c從名字來看就可以知道是一門超c語言,所以了解c語言的記憶體模型對於理解objective c的記憶體管理有很大的幫助。c語言記憶體模型圖如下 從圖中可以看出記憶體被分成了5個區,每個區儲存的內容如下 棧區在什麼時候釋放記憶體呢?我們通過下面的乙個例子來說明下 void prin...