一、動態儲存裝置分配
在數組一章中,曾介紹過數組的長度是預先定義好的,在整個程式中固定不變。C語言中不允許動態數群組類型。
例如:
int n;
scanf("%d",&n);
int a[n];
用變數表示長度,想對數組的大小作動態說明,這是錯誤的。但是在實際的編程中,往往會發生這種情況,即所需的記憶體空間取決於實際輸入的資料,而無法預先確定。對於這種問題,用數組的辦法很難解決。為瞭解決上述問題,C語言提供了一些記憶體管理函數,這些記憶體管理函數可以按需要動態地分配記憶體空間,也可把不再使用的空間回收待用,為有效地利用記憶體資源提供了手段。
常用的記憶體管理函數有以下三個:
1.分配記憶體空間函數malloc
調用形式:
(類型說明符*)malloc(size)
功能:在記憶體的動態儲存裝置區中分配一塊長度為"size"位元組的連續地區。函數的傳回值為該地區的首地址。
“類型說明符”表示把該地區用於何種資料類型。
(類型說明符*)表示把傳回值強制轉換為該類型指標。
“size”是一個無符號數。
例如:
pc=(char *)malloc(100);
表示分配100個位元組的記憶體空間,並強制轉換為字元數群組類型,函數的傳回值為指向該字元數組的指標,把該指標賦予指標變數pc。
2.分配記憶體空間函數 calloc
calloc 也用於分配記憶體空間。
調用形式:
(類型說明符*)calloc(n,size)
功能:在記憶體動態儲存裝置區中分配n塊長度為“size”位元組的連續地區。函數的傳回值為該地區的首地址。
(類型說明符*)用於強制類型轉換。
calloc函數與malloc 函數的區別僅在於一次可以分配n塊地區。
例如:
ps=(struet stu*)calloc(2,sizeof(struct stu));
其中的sizeof(struct stu)是求stu的結構長度。因此該語句的意思是:按stu的長度分配2塊連續地區,強制轉換為stu類型,並把其首地址賦予指標變數ps。
二、釋放記憶體空間函數free
調用形式:
free(void*ptr);
功能:釋放ptr所指向的一塊記憶體空間,ptr是一個任意類型的指標變數,它指向被釋放地區的首地址。被釋放區應是由malloc或calloc函數所分配的地區。
【例1】分配一塊地區,輸入一個學生資料。
main()
{
struct stu
{
int num;
char *name;
char sex;
float score;
} *ps;
ps=(struct stu*)malloc(sizeof(struct stu));
ps->num=102;
ps->name="Zhang ping";
ps->sex='M';
ps->score=62.5;
printf("Number=%d Name=%s ",ps->num,ps->name);
printf("sex=%c Score=%f ",ps->sex,ps->score);
free(ps);
}
本例中,定義了結構stu,定義了stu類型指標變數ps。然後分配一塊stu大記憶體區,並把首地址賦予ps,使ps指向該地區。再以ps為指向結構的指標變數對各成員賦值,並用printf輸出各成員值。最後用free函數釋放ps指向的記憶體空間。整個程式包含了申請記憶體空間、使用記憶體空間、釋放記憶體空間三個步驟,實現儲存空間的動態分配。
free()只能釋放堆記憶體,也就是malloc()建立的
前段時間,看某人代碼的時候看到
free(q);
q->lru = *blk_head_lru.next;
這樣一句,感覺有點奇怪,為啥一個指標free後,還能賦值,而結果也正確。
後百思不得其解。
後Google之,發現free後只是做了個標記,告訴系統這塊記憶體不用了,一旦調用後, 那個地址是不被保護的, 也就是說其他的變數隨時可能佔用那個地址。
後想到如果free後,再malloc一個新變數那麼那個值是否被覆蓋了?
寫了一代碼試了試
#include <stdio.h>
#include <malloc.h>
int main()
{
int *a = (int *)malloc(sizeof(int));
*a = 5;
free(a);
printf("a = %d\n",*a);
*a = 4;
printf("a = %d\n",*a);
int *b;
b = (int *)malloc(sizeof(int));
printf("a = %d\n",*a);
return 0;
}
VS2005編譯通過。
如果有free
結果是
a = -572662307
a = 4
a = -842150451
如果注釋掉free
a = 5
a = 4
a = 4
這是為什麼呢。