calloc、malloc、realloc函數的區別及用法!

PS:找不到原地址

                          calloc、malloc、realloc函數的區別及用法!

三者都是分配內存,都是stdlib.h庫裏的函數,但是也存在一些差異。

(1)malloc函數。其原型void *malloc(unsigned int num_bytes);
num_byte爲要申請的空間大小,需要我們手動的去計算,如int *p = (int *)malloc(20*sizeof(int)),如果編譯器默認int爲4字節存儲的話,那麼計算結果是80Byte,一次申請一個80Byte的連續空間,並將空間基地址強制轉換爲int類型,賦值給指針p,此時申請的內存值是不確定的。

(2)calloc函數,其原型void *calloc(size_t n, size_t size);
其比malloc函數多一個參數,並不需要人爲的計算空間的大小,比如如果他要申請20個int類型空間,會int *p = (int *)calloc(20, sizeof(int)),這樣就省去了人爲空間計算的麻煩。但這並不是他們之間最重要的區別,malloc申請後空間的值是隨機的,並沒有進行初始化,而calloc卻在申請後,對空間逐一進行初始化,並設置值爲0;

實例:

  1.     int *p = (int *)malloc(20*sizeof(int));
  2.     int *pp = (int *)calloc(20, sizeof(int));
  3.     int i;
  4.     
  5.     printf("malloc申請的空間值:\n\n");
  6.     for ( i=0 ; i < 20; i++)
  7.     {
  8.         printf("%d ", *p++);
  9.     }
  10.     printf("\n\n");
  11.     printf("calloc申請的空間的值:\n\n");
  12.     for ( i=0 ; i < 20; i++)
  13.     {
  14.         printf("%d ", *pp++);
  15.     }
  16.     printf("\n");

結果:

很多人會疑問:既然calloc不需要計算空間並且可以直接初始化內存避免錯誤,那爲什麼不直接使用calloc函數,那要malloc要什麼用呢?
實際上,任何事物都有兩面性,有好的一面,必然存在不好的地方。這就是效率。calloc函數由於給每一個空間都要初始化值,那必然效率較malloc要低,並且現實世界,很多情況的空間申請是不需要初始值的,這也就是爲什麼許多初學者更多的接觸malloc函數的原因。

(3)realloc函數和上面兩個有本質的區別,其原型void realloc(void *ptr, size_t new_Size)
用於對動態內存進行擴容(及已申請的動態空間不夠使用,需要進行空間擴容操作),ptr爲指向原來空間基址的指針, new_size爲接下來需要擴充容量的大小。
實例:

  1. int main(void)
  2. {
  3.     const int size = 2000;
  4.     int *p = (int *)malloc(20*sizeof(int));
  5.     int *pp = (int *)realloc(p, size*sizeof(int));
  6.     
  7.     printf("原來的p_Address:%x   擴容後的pp_Address:%x \n\n", p, pp);
  8.     
  9.     return 0;
  10. }


結果:

可從圖看出,擴容後地址和原先地址是不一樣的,但是這僅僅取決於擴容的內存大小。

實際上:

如果size較小,原來申請的動態內存後面還有空餘內存,系統將直接在原內存空間後面擴容,並返回原動態空間基地址;如果size較大,原來申請的空間後面沒有足夠大的空間擴容,系統將重新申請一塊(20+size)*sizeof(int)的內存,並把原來空間的內容拷貝過去,原來空間free;如果size非常大,系統內存申請失敗,返回NULL,原來的內存不會釋放。注意:如果擴容後的內存空間較原空間小,將會出現數據丟失,如果直接realloc(p, 0);相當於free(p).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章