1. 程式人生 > 其它 >calloc、malloc、realloc函式的區別及用法

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;

    int *p = (int *)malloc(20*sizeof(int));
    int *pp = (int *)calloc(20, sizeof(int));
    int i;
    
    printf("malloc申請的空間值:\n\n");
    for ( i=0 ; i < 20; i++)
    {
        printf("%d ", *p++);
    }
    printf("\n\n");
    printf("calloc申請的空間的值:\n\n");
    for ( i=0 ; i < 20; i++)
    {
        printf("%d ", *pp++);
    }
    printf("\n");

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

  (3)realloc函式和上面兩個有本質的區別,其原型void realloc(void *ptr, size_t new_Size)


      用於對動態記憶體進行擴容(及已申請的動態空間不夠使用,需要進行空間擴容操作),ptr為指向原來空間基址的指標, new_size為接下來需要擴充容量的大小。

int main(void)
{
    const int size = 2000;
    int *p = (int *)malloc(20*sizeof(int));
    int *pp = (int *)realloc(p, size*sizeof(int));
    
    printf("原來的p_Address:%x   擴容後的pp_Address:%x \n\n", p, pp);
    
    return 0;
}

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

進一步分析:

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