為什么動態(tài)分配內(nèi)存?
int a[5]; //ok
int length = 5;
int a[length]; //不ok
- 數(shù)組的長度必須事先指定,而且只能是常量,不能是變量
- 因?yàn)閿?shù)組長度只能是常量,所以它的長度不能在函數(shù)運(yùn)行的過程當(dāng)中動態(tài)地擴(kuò)充和縮小
- 對于數(shù)組所占內(nèi)存空間無法手動釋放,只能在函數(shù)運(yùn)行結(jié)束后由系統(tǒng)自動釋放,所以在一個函數(shù)中定義的數(shù)組只能在該函數(shù)運(yùn)行期間被使用
- 動態(tài)分配內(nèi)存就不存在以上問題,因?yàn)閯討B(tài)內(nèi)存是手動釋放,理論上可以在任意時刻釋放,在釋放之前,即便是函數(shù)運(yùn)行結(jié)束,其他函數(shù)仍可繼續(xù)使用它。(程序運(yùn)行結(jié)束時系統(tǒng)為該程序分配的所有內(nèi)存空間都會被釋放)
動態(tài)分配內(nèi)存的使用
- 動態(tài)分配內(nèi)存主要涉及到 malloc calloc realloc 三個函數(shù)
- 動態(tài)分配內(nèi)存必須指針接收
- 動態(tài)分配內(nèi)存返回類型為 void *
- 動態(tài)分配內(nèi)存可能失敗 返回NULL ,使用前應(yīng)判空
- 動態(tài)分配的內(nèi)存不會自動釋放,必須手動釋放
- malloc ,分配內(nèi)存
int *p = (int *)malloc(10); //動態(tài)申請10個字節(jié)的大小的連續(xù)空間,返回的是首地址
- calloc,分配內(nèi)存并初始化為0,
int *p = (int *)calloc(10,2); //動態(tài)申請 10*2 個字節(jié)的大小的連續(xù)空間,并初始化為0,返回的是首地址
- realloc,動態(tài)調(diào)整已分配的內(nèi)存,返回調(diào)整后的新分配的連續(xù)空間的首地址,同時將調(diào)整之前的地址中的值復(fù)制到新地址中
int *p = (int *)malloc(20 * sizeof(int));
int *p1 = (int *)realloc(p, 10*sizeof(int));
//擴(kuò)大已分配的內(nèi)存,返回已擴(kuò)大后的新分配的連續(xù)空間的首地址,同時將擴(kuò)大之前的地址中的值復(fù)制到新地址中
動態(tài)分配內(nèi)存的釋放
- 動態(tài)分配的內(nèi)存不會自動釋放,必須手動釋放
# include <stdio.h>
# include <stdlib.h>
int main(void)
{
int *p = malloc(sizeof(int));
*p = 10;
printf("p = %p\n", p);
free(p);
printf("p = %p\n", p);
p = NULL;
return 0;
}
釋放前后,p 所指向的內(nèi)存地址是一樣的。所以釋放后 p 所指向的仍然是那塊內(nèi)存空間。既然指向的仍然是那塊內(nèi)存空間,那么就仍然可以往里面寫數(shù)據(jù)??墒轻尫藕笤搩?nèi)存空間已經(jīng)不屬于它了,該內(nèi)存空間可能會被分配給其他變量使用。如果其他變量在里面存放了值,而現(xiàn)在用 p 往里面寫入數(shù)據(jù)就會把那個值給覆蓋,這樣就會造成程序錯誤。所以當(dāng)指針變量被釋放后,要立刻把它的指向改為 NULL。
- 只有動態(tài)創(chuàng)建的內(nèi)存才能用 free 把它釋放掉,靜態(tài)內(nèi)存是不能用free釋放的。靜態(tài)內(nèi)存只能由系統(tǒng)釋放