C/C++中的malloc、calloc和realloc

1. malloc

原型:extern void *malloc(unsigned int num_bytes);
頭文件:Visual C++6.0中可以用malloc.h或者stdlib.h
功能:分配長度爲num_bytes字節的內存塊
返回值:如果分配成功則返回指向被分配內存的指針(此存儲區中的初始值不確定),否則返回空指針NULL。當內存不再使用時,應使用free()函數將內存塊釋放。函數返回的指針一定要適當對齊,使其可以用於任何數據對象。

函數聲明:void *malloc(size_t size);

說明:malloc向系統申請分配指定size個字節的內存空間。返回類型是void*類型。void*表示未確定類型的指針。C,C++規定,void* 類型可以強制轉換爲任何其它類型的指針。

備註:
  void*表示未確定類型的指針,更明確的說是指申請內存空間時還不知道用戶是用這段空間來存儲什麼類型的數據(比如是char還是int或者...)
  從函數聲明上可以看出。mallocnew至少有兩個不同:`new返回指定類型的指針,並且可以自動計算所需要大小。

比如:

int *p;
p = new int; //返回類型爲int* 類型(整數型指針),分配大小爲 sizeof(int);

// 或:
int* parr;
parr = new int [100]; //返回類型爲 int* 類型(整數型指針),分配大小爲 sizeof(int) * 100;

malloc則必須要由我們計算字節數,並且在返回後強行轉換爲實際類型的指針。

int* p;
//分配128個(可根據實際需要替換該數值)整型存儲單元,並將這128個連續的整型存儲單元的首地址存儲到指針變量p中
p = (int *) malloc (sizeof(int)*128);
//分配12個double型存儲單元,並將首地址存儲到指針變量pd中
double *pd=(double *) malloc (sizeof(double)*12);

使用malloc時要注意:

  • malloc函數返回的是void *類型。對於C++,如果你寫成:p = malloc (sizeof(int));則程序無法通過編譯,報錯:“不能將void*賦值給int *類型變量”。所以必須通過(int *)來將強制轉換。而對於C,沒有這個要求,但爲了使C程序更方便的移植到C++中來,建議養成強制轉換的習慣
  • 函數的實參爲sizeof(int),用於指明一個整型數據需要的大小。如果你寫成:
int* p = (int *) malloc (1);

代碼也能通過編譯,但事實上只分配了1個字節大小的內存空間,當你往裏頭存入一個整數,就會有3個字節無家可歸,而直接“住進鄰居家”!造成的結果是後面的內存中原有數據內容被改寫。

malloc內部機制

malloc函數的實質體現在,它有一個將可用的內存塊連接爲一個長長的列表的所謂空閒鏈表。調用malloc函數時,它沿連接表尋找一個大到足以滿足用戶請求所需要的內存塊。然後,將該內存塊一分爲二(一塊的大小與用戶請求的大小相等,另一塊的大小就是剩下的字節)。接下來,將分配給用戶的那塊內存傳給用戶,並將剩下的那塊(如果有的話)返回到連接表上。調用free()函數時,它將用戶釋放的內存塊連接到空閒鏈上。到最後,空閒鏈會被切成很多的小內存片段,如果這時用戶申請一個大的內存片段,那麼空閒鏈上可能沒有可以滿足用戶要求的片段了。於是,malloc函數請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各內存片段,對它們進行整理,將相鄰的小空閒塊合併成較大的內存塊。如果無法獲得符合要求的內存塊,malloc函數會返回NULL指針,因此在調用malloc動態申請內存塊時,一定要進行返回值的判斷。

2. calloc

函數聲明:void *calloc(unsigned n,unsigned size);
功能:在內存的動態存儲區中分配n個長度爲size的連續空間,函數返回一個指向分配起始地址的指針,如果分配不成功,返回NULL

malloc的區別:
calloc在動態分配完內存後,自動初始化該內存空間爲零,而malloc不初始化,裏邊數據是隨機的垃圾數據。

3. realloc

原型:extern void *realloc(void *mem_address, unsigned int newsize);
頭文件:#include <stdlib.h>
功能:先判斷當前的指針是否有足夠的連續空間,如果有,擴大mem_address指向的地址,並且將mem_address返回,如果空間不夠,先按照newsize指定的大小分配空間,將原有數據從頭到尾拷貝到新分配的內存區域,而後釋放原來mem_address所指內存區域,同時返回新分配的內存區域的首地址。即重新分配存儲器塊的地址。
返回值:如果重新分配成功則返回指向被分配內存的指針,否則返回空指針NULL
使用語法:指針名 = (數據類型*)realloc(要改變內存大小的指針名,新的大小)。//新的大小一定要大於原來的大小不然的話會導致數據丟失!

注意:這裏原始內存中的數據還是保持不變的。當內存不再使用時,應使用free()函數將內存塊釋放。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章