說說動態記憶體分配
當編寫程式時,偶爾會不確定陣列的大小(包括儲存字串的陣列)。較為方便的做法是等到程式執行時再來確定陣列的實際大小。
在標準C中,提供了3個庫函式:malloc(),calloc()和realloc()。那麼他們有什麼區別,分別用在什麼場合呢?
malloc()函式
函式原型:
void * malloc(size_t num_byte)
引數介紹:
- 一般來說,如果申請成功會它返回一個無型別(通用)指標,使用者需要通過強制型別轉換將其轉換為你需要的型別。如果申請失敗,函式返回空指標。
- num_byte為你申請的空間大小,它固定以8位單位元組為單位。在實際程式設計中,為了程式的可移植性,往往使用sizeof()運算子來計算申請的單個元素資料型別所佔的位元組大小。
int *p; p = (int *)malloc( n * sizeof(int) ); if ( NULL = p ){ printf("malloc failed!"); exit(EXIT_FAILURE); } ...
- 需要注意的是,它從記憶體的堆(heap)資源中分配空間,且不會對分配的記憶體資源進行初始化。
calloc()函式
函式原型:
void *calloc(size_t n_memb,size_t size)
引數介紹:
- 同malloc()函式,如果申請成功會它返回一個無型別(通用)指標,使用者需要通過強制型別轉換將其轉換為你需要的型別。如果申請失敗,函式返回空指標。
- n_memb為申請的元素個數,size為每個元素的所佔位元組大小。
- 在分配了記憶體之後,會以對所有位清零的方式進行初始化。
- 下例展示為n個整數的陣列分配記憶體空間,並初始化陣列元素為0。
int *a; a = (int *)calloc( n*sizeof(int) ); if ( NULL = a ){ printf("malloc failed!"); exit(EXIT_FAILURE); }
- 通過呼叫以1為第一個實參的方式,可以為任何型別的資料項分配已初始化為零的空間。
realloc()函式
一旦分配完了空間,稍後可能會發現空間過小或者過大。此時該函式可以調整原來空間的大小以適應新的要求。
函式原型:
void *realloc(void *ptr, size_t size)
引數介紹:
- ptr必須指向先前通過malloc()或calloc()或realloc()函式分配的空間指標。
- size表示記憶體塊的新尺寸,它可以大於或小於原尺寸。
使用原則:
- 它不會對擴充套件的記憶體塊進行初始化。
- 如果分配失敗,返回空指標,且原資料塊不受影響。
- 如果ptr設定為空指標,行為同malloc()函式。
- 如果size設定為0,行為同free()函式,即釋放ptr所指空間資源。
- 在擴大空間的情況下,realloc()會盡量在原地進行擴充,如果無法原地擴充(記憶體塊後面的空間已經用於其他目的),它會在別處重新分配記憶體塊,並把舊塊中的資料複製過去。所以,在呼叫完該函式後,切記更新所有指向該記憶體塊的指標變數。
free()函式
在講解了空間分配函式後,不得不提的就是要及時!及時!及時!釋放之前申請的空間。否則隨著程式的執行,會產生大量記憶體垃圾(記憶體洩露),最後系統會因資源耗盡而嗝屁。
函式原型:
void free(void *ptr)
引數介紹:
- 使用它很容易,你只要把你之前申請的現在不需要的記憶體塊指標傳遞給它就好了。
p = malloc(...); ... free(p);
- 雖然利用free()函式釋放了p指向的記憶體空間,但p的值並沒有改變。如果不把p及時及時及時指向空(NULL),會產生懸空指標,如果之後程式試圖修改它指向的記憶體資料,會有程式崩潰等損失慘重的後果。