Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc() Functions

This C Tutorial explains various Dynamic memory Allocation Functions viz. – malloc(), calloc(), realloc() and free() in C Language, with examples.

Functions malloc(), calloc(), realloc() are used for dynamic allocation while free() used for deallocation of block allocated to by malloc(), calloc() or realloc(). Let us differentiate among them by experimenting, first we consider malloc(),

/*
 * malloc_not_ini.c -- program displays memory allocated by malloc is not
 * initialized
 */
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    char *pc, chars, i;
 
    puts("**Program displays malloc() returns uninitialized block**");
    printf("Specify no. of characters to which memory to allocate,\n");
    scanf("%d", &chars);
 
    /* now allocate memory */
    pc = (char *)malloc(chars * sizeof(char));
 
    /* verify if allocation successful */
    if (pc == NULL) {
            puts("Error: Allocation Failed!");
            exit(EXIT_FAILURE);
    }
 
    /* let us see the contents of allocated block */
    i = 0;
    printf("Allocated block, an array of %d chars, contains values:",
            chars);
    while (i < chars) {
            printf("%2c", *(pc + i));
            i++;
    }
 
    /* Now we free allocated block back to pool of available memory */
    free(pc);
 
    puts("");
    return 0;
}

Output of the above program, for some arbitrary character’s value, as follows,

**Program displays malloc() returns uninitialized block**
Specify no. of characters to which memory to allocate,
25
Allocated block, an array of 25 chars, contains values:

Notice here that malloc() takes one argument, size in bytes, and allocates requested block of memory and returns pointer of type void * to the start of that block. If function fails, it returns NULL. Therefore, it’s mandatory to verify if pointer returned is NOT NULL. Further, block allocated isn’t initialized.

Let us consider calloc() now,

advertisement
advertisement
/*
 * calloc_ini.c -- program displays memory allocated by calloc is
 * initialized to 0
 */
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    int *pi, ints, i;
 
    puts("**Program displays calloc() initializes memory"
         " It allocates**");
    printf("Specify no. of integers to which memory to allocate,\n");
    scanf("%d", &ints);
 
    /* now allocate memory */
    pi = (int *)calloc(ints, sizeof(int));
 
    /* verify if allocation successful */
    if (pi == NULL) {
            puts("Error: Allocation Failed!");
            exit(EXIT_FAILURE);
    }
 
    /* let us see if allocated block is initialized with zeroes */
    i = 0;
    printf("Allocated block, an array of %d ints, is initialized with:",
            ints);
    while (i < ints) {
            printf("%2d", *(pi + i));
            i++;
    }
 
    /* free block up back to pool of available memory */
    free(pi);
 
    puts("");
    return 0;
}

Output as follows,

**Program displays calloc() initializes memory It allocates**
Specify no. of integers to which memory to allocate,
6
Allocated block, an array of 6 ints, is initialized with: 0 0 0 0 0 0

What we noticed here is that calloc() takes two arguments, first is number of elements and second is type of element and computes number of bytes to allocate. It allocates requested block and returns pointer to void pointing to beginning of block. If fails, returns NULL. Unlike malloc(), calloc() initializes the block with zeroes.

Note: Join free Sanfoundry classes at Telegram or Youtube

Next, we turn to consider is realloc(),

/*
 * realloc.c -- Let's get resize previously allocated block and
 * free that up for reuse
 */
/* void *realloc(void *, size_t num_bytes) */ /* realloc resizes */
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    int *pi, i, num = 0;
    int *pi1 = 0;   /* pointer set to NULL */
 
    puts("\nLet's try to get block of memory for integers u want...\n");
    scanf("%d", &num);
 
    /* assigned to int * type */
    pi = malloc(num * sizeof(int));
 
    /* confirm if allocation is done */
    if (pi == NULL) {
            puts("Error: System short of memory!");
            exit(1);
    }
 
    puts("Good! Now, let's use dynamic memory...\n");
    printf("User type in %d integers one by one...\n", num);
    for (i = 0; i < num; i++)
            scanf("%d", (pi + i));
 
    puts("");
 
    printf("User, let's see what had u typed...\n");
    for (i = 0; i < num; i++)
            printf("%3d", *(pi + i));
 
    puts("");
 
    puts("Yeah, I want to resize the previously allocated chunk,\n"
            "specify another value for integers you want now...");
    scanf("%d", &num);
    /* reallocate block using realloc() function */
    pi1 = realloc(pi, num * sizeof(int));
 
    /* confirm if allocation is done */
    if (pi1 == NULL) {
            puts("Error: System short of memory!");
            exit(1);
    }
 
    printf("Let's see the contents of resized block of %d integers.\n",
             num);
    for (i = 0; i < num; i++)
           printf("%3d", *(pi1 + i));
 
    puts("");
 
    puts("Good! Now, let's use new chunk...\n");
    printf("User type in %d integers one by one...\n", num);
    for (i = 0; i < num; i++)
            scanf("%d", (pi1 + i));
 
    puts("");
 
    printf("User, let's see what had u typed...\n");
    for (i = 0; i < num; i++)
           printf("%3d", *(pi1 + i));
 
    puts("");
    puts("Let's return allocated memory to system for reuse.");
    free(pi1);      /* remember don't double free up memory */
 
    puts("Thank you!\n");
    return 0;
}

Output of the above program,

Let us try to get block of memory for integers u want...
 
6
Good! Now, let's use dynamic memory...
 
User type in 6 integers one by one...
1
2
3
4
5
6
 
User, let us see what had u typed...
  1  2  3  4  5  6
Yeah, I want to resize the previously allocated chunk,
specify another value for integers you want now...
5
Let us see the contents of resized block of 5 integers.
  1  2  3  4  5
Good! Now, let's use new chunk...
 
User type in 5 integers one by one...
5
6
7
8
9
 
User, let us see what had u typed...
  5  6  7  8  9
Let's return allocated memory to system for reuse.
Thank you!

Well! realloc() takes two arguments, first pointer to void and second is size in bytes. Since, realloc() can be used to resize the previously allocated block to by malloc() or calloc(). Therefore, first argument to realloc is pointer to the previously allocated block. realloc() allocates requested chunk to some other location, makes it larger or smaller as specified by the size and copies here contents of previously allocated block. Since, new block allocated is different from previously allocated one, make sure to use pointer returned by realloc()! After you are done, call free() to return the chunk back to pool of available memory.

advertisement

Let’s consider free() function,

        void free(void *);

free() function frees up chunk and returns it to the pool of available memory.

advertisement

Sanfoundry Global Education & Learning Series – 1000 C Tutorials.

If you wish to look at all C Tutorials, go to C Tutorials.

If you find any mistake above, kindly email to [email protected]

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.