C語言記憶體分配 通俗理解

2021-07-24 10:55:40 字數 3247 閱讀 6887

最近很多同學希望了解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...