動態記憶體分配

2021-08-17 19:33:45 字數 4470 閱讀 3193

c語言

記憶體分配方式

<1>從靜態儲存區域分配.

內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在.例如全域性變數、static變數.

<2>在棧上建立

在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放.棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限

通常將棧稱作函式呼叫棧。

<3>從堆上分配.

程式在執行的時候用malloc或new申請任意多少的記憶體,程式設計師自己負責在何時用free或delete釋放記憶體.動態記憶體的生存期由使用者決定,使用非常靈活,但問題也最多.

c語言中堆上的

記憶體申請相關的函式主要有 calloc、malloc、free、realloc等.

三個

申請空間

函式的申明分別是:

void* malloc(unsigned size);

void* realloc(void* ptr, unsigned newsize);

void* calloc(size_t numelements, size_t sizeofelement);

它們的返回值都是請求系統分配的位址,如果請求失敗就返回null.

<1>malloc在堆上申請指定大小的記憶體空間

並且這部分空間沒有被初始化,需要函式呼叫者將其初始化。

<2>realloc則對malloc申請的記憶體進行大小的調整

可擴大或縮小。

<3>calloc則將初始化這部分的記憶體,設定為0.

<4>申請的記憶體最終需要通過函式free來釋放.

在堆上申請的空間不用時要及時釋放,否則容易造成記憶體洩漏。指標最後也要賦空(null),不然形成野指標是相當危險的。在堆上申請空間時也會出現記憶體碎片。

注意:使用這幾個函式申請記憶體時,真正申請出來的記憶體大小要比想要申請的記憶體大,在這一部分多出來的記憶體中一部分在分布頭部,一部分分布在尾部儲存著,分別儲存著這部分記憶體塊頭部和尾部的資訊,當要釋放這一部分記憶體時,根據頭部資訊找到尾部資訊並計算大小來釋放記憶體(將頭部與尾部一起釋放),這就是為什麼free時不用傳記憶體塊的大小的原因。

(1)函式malloc()

在記憶體的動態儲存區中分配一塊長度為size位元組的連續區域,引數size為需要記憶體空間的長度,返回該區域的首地          址.

(2)函式calloc()

與malloc相似,引數sizeofelement為申請位址的單位元素長度,numelements為元素個數,即在記憶體中申請                   numelements*sizeofelement位元組大小的連續位址空間.

(3)函式realloc()

給乙個已經分配了位址的指標重新分配空間,引數ptr為原有的空間位址,newsize是重新申請的位址長度.三個函式的區別:

(1)函式malloc不能初始化所分配的記憶體空間,而函式calloc能.如果由malloc()函式分配的記憶體空間原來沒有被使用      過,則其中的每一位可能都是0;反之, 如果這部分記憶體曾經被分配過,則其中可能遺留有各種各樣的資料.也就是說,使用    malloc()函式的程式開始時(記憶體空間還沒有被重新分配)能正常進行,但經過一段時間(記憶體空間還已經被重新分配)可能會     出現問題.

(2)函式calloc() 會將所分配的記憶體空間中的每一位都初始化為零,也就是說,如果你是為字元型別或整數型別的元素分    配記憶體,那麼這些元素將保證會被初始化為0;如果你是為指標型別的元素分配記憶體,那麼這些元素通常會被初始化為空指標;     如果你為實型資料分配記憶體,則這些元素會被初始化為浮點型的零.

(3)函式malloc向系統申請分配指定size個位元組的記憶體空間.返回型別是 void*型別.void*表示未確定型別的指標.c,c++     規定,void* 型別可以強制轉換為任何其它型別的指標.

(4)realloc可以對給定的指標所指的空間進行擴大或者縮小,無論是擴張或是縮小,原有記憶體的中內容將保持不變.當     然,對於縮小,則被縮小的那一部分的內容會丟失.realloc並不保證調整後的記憶體空間和原來的記憶體空間保持同一記憶體地      址.相反,realloc返回的指標很可能指向乙個新的位址.

(5)realloc是從堆上分配記憶體的.當擴大一塊記憶體空間時,realloc()試圖直接從堆上現存的資料後面的那些位元組中獲得   附加的位元組,如果能夠滿足,自然是最好的,否則就在

堆上

乙個足夠大的自由塊,

開闢所需大小的總空間,然後將原有的  資料拷貝到

新的位置,而

舊的記憶體塊則還給堆。由於位置的改變會導致原先儲存記憶體塊首位址的指標的值的改變。如下所示:

#include

#include

int main()   

//輸出結果為:

//          p=0x30419a8

//          q=0x30419a8

#include

#include

int main()   

//輸出結果為:

//        p=0xe13120

//        q=0xe119a8

動態記憶體分配

在c 中建立乙個物件時,我們必須要為這個物件申請一塊記憶體,而且要用建構函式對這塊記憶體進行初始化。c 中的new和delete相對於c的庫函式malloc和free在這方面有很大的優勢,所以我們主要講的是運算子new和delete。當用new來建立乙個物件時,它會自動在堆裡為物件分配記憶體並且為這...

動態記憶體分配

為什麼使用動態記憶體分配?c語言中的一切操作都是基於記憶體的 變數和陣列都是記憶體的別名,如何分配這些記憶體由編譯器在編譯期間決定 定義陣列的時候必須指定陣列唱的 而陣列長度是在編譯期就必須決定的 需求 程式執行的過程中,可能需要使用一些額外的記憶體空間 malloc和free malloc和fre...

動態記憶體分配

c的儲存類別有4種 自動的 auto 靜態的 statics 暫存器的 register 外部的 extern 全域性變數時分配在記憶體中的靜態儲存區 靜態區域性變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元,是在編譯時賦初值的,只賦初值一次,在程式執行時它已有初值,以後每次呼叫函式時不再重新賦初...