在此之前,我們用於存儲數據的變量和數組都必須在說明部分進行定義。C編譯程序通過定義語句了解它們所需存儲空間的大小,並預先為其分配適當的內存空間。這些空間一經分配,在變量或數組的生存期內是固定不變的。故稱這種分配方式為“靜態存儲分配”。
C語言中還有一種稱作“動態存儲分配”的內存空間分配方式:在程序執行期間需要空間來存儲數據時,通過“申請”得到指定的內存空間;當有閒置不用的空間時,可以隨時將其釋放。用戶可以通過調用C語言提供的標准庫函數來實現動態分配,從而得到指定數目的內存空間或釋放指定的內存空間。
ANSI C標准為動態分配系統定義了四個函數:malloc、calloc、free、realloc。使用這些函數時,必須在程序開頭包含頭文件 stdlib.h。
ANSI C標准規定 malloc 函數返回值類型為 void*,函數的調用形式為:malloc(size)。要求 size 的類型為 unsigned int。
malloc 函數用來分配 size 個字節的存儲區,返回一個指向存儲區首地址的基類型為 void 的地址。若沒有足夠的內存單元供分配,函數返回空(NULL)。
假設 short int 型數據占2字節、float 型數據占4字節存儲單元,則以下程序段將使 pi 指向一個 short int 類型的存儲單元,使 pf 指向一個 float 類型的存儲單元:
short int *pi;
float *pf;
pi = (short*)malloc(2);
pf = (float*)malloc(4);
if (pi != NULL) *pi = 6;
if (pf != NULL) *pf = 3.8;
由於在 ANSI C 中 malloc 函數返回的指針為 void*(無值型),故在調用函數時,必須利用強制類型轉換將其轉成所需的類型。上面的程序段中,調用 malloc 函數時括號中的 * 號不可少,否則就轉換成普通變量類型而不是指針類型了。
由動態分配得到的存儲單元沒有名字,只能靠指針來引用它。一旦指針改變指向,元存儲單元及所存儲數據都將無法再引用。通過 malloc 函數所分配的動態存儲單元中沒有初值。
在動態申請存儲空間時,若不能確定數據類型所占字節數,可以使用 sizeof 運算符來求得。
例如:
pi = (int*)malloc(sizeof(int));
pf = (float*)malloc(sizeof(float));
這是一種常用形式。此時將由系統來計算指定類型的字節數,采用這種形式將有利於程序的移植。
函數的調用形式為:
free(p);
這裡指針變量 p 必須指向由動態分配函數 malloc 或 calloc 分配的地址。free 函數將指針 p 所指的存儲空間釋放,使這部分空間可以由系統重新支配。此函數沒有返回值。
ANSI C 標准規定 calloc 函數返回值的類型為 void*,函數的調用形式為:
calloc(n, size);
要求 n 和 size 的類型都為 unsigned int。
calloc 函數用來給 n 個同一類型的數據項分配連續的存儲空間,每個數據項的長度為 size 個字節。若分配成功,函數返回存儲空間的首地址;否則返回空。通過調用 calloc 函數所分配的存儲單元,系統自動賦初值為0。例如:
char *ps;
ps = (char*)calloc(10, sizeof(char));
以上函數調用語句開辟了10個連續的 char 類型的存儲單元,由 ps 指向存儲單元的首地址。每個存儲單元可以存放一個字符。
使用 calloc 函數動態開辟的存儲單元相當於開辟了一個一維數組。函數的第一個參數決定了一維數組的大小;第二個參數決定了數組元素的類型。函數的返回值就是數組的首地址。使用 calloc 函數開辟的動態存儲單元,可以用 free 函數釋放。