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

Dynamic memory allocation in C is essential for efficiently managing memory based on the actual needs of a program. It allows the size of data structures, such as arrays, to be adjusted at runtime. The C programming language offers four standard library functions for this purpose, all defined in the <stdlib.h> header file:

  • malloc()
  • calloc()
  • free()
  • realloc()

Let’s explore each of these functions in more detail.

Important: Let suppose, in a fixed-size array of 8 elements, if you only need to store 5 elements, you’re wasting memory. Similarly, if you need to add 2 more elements, the fixed size won’t accommodate a total of 10. To effectively manage memory according to your needs, dynamic memory allocation is the ideal solution.

 1. malloc() method in C

The malloc function in C is used to dynamically allocate a large block of memory of a specified size. It returns a pointer of type void, which can be cast to any other pointer type. However, it does not initialize the allocated memory, so each block contains garbage values by default.

Syntax of malloc() in C

(cast-type*) ptr = (cast-type*) malloc(byte-size)

For Example:

Int *ptr = (int*) malloc(1000 * sizeof(int));

In this case, since the size of an int is typically 4 bytes, this statement allocates a total of 4000 bytes of memory. The pointer ptr then holds the address of the first byte in the allocated memory block.

Malloc () Dynamic Memory Allocation in C

Important: If you try to allocate memory using malloc() and there isn’t enough space, it will return a NULL pointer. For example:

int *ptr = (int*) malloc(1000000000 * sizeof(int)); // Trying to allocate a large amount of memory

if (ptr == NULL) {

    printf(“Memory allocation failed!\n”);

} else {

    // Use the memory

}

Example of malloc() in C

#include <stdio.h>
#include <stdlib.h> // Required for malloc and free
int main() {
    int n;
    printf("Enter the number of elements: ");
    scanf("%d", &n);
    int *array = (int *)malloc(n * sizeof(int)); // Dynamically allocate memory on the heap
    if (array == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }

    printf("Enter %d elements:\n", n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &array[i]);
    }
    printf("Fully Dynamic Array Elements:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
    free(array); // Free the allocated memory
    return 0;
}

Output

Enter the number of elements: 5
Enter 5 elements:
3
5
67
8
8
Fully Dynamic Array Elements:
3 5 67 8 8

2. calloc() method in C

The calloc function, which stands for “contiguous allocation,” is used in C to dynamically allocate a specified number of blocks of memory for a given type. It is similar to malloc() but has two key differences:

  • It initializes each allocated block to a default value of 0, whereas malloc() leaves the memory uninitialized, which may result in garbage values.
  • It takes two parameters compared to malloc(), which only takes one.

Syntax of calloc() in C

(cast-type*) ptr = (cast-type*)calloc(n, element-size);
Here, n is the no. of elements, and “element-size” is the size of each element.

Calloc() Dynamic Memory Allocation in C

 

For Example: 

float *ptr = (float*) calloc(20, sizeof(float));

This statement allocates contiguous memory space for 20 elements, each of type float.

Note: similarly to malloc, while using calloc, If there is insufficient memory available, the allocation will fail, and a NULL pointer will be returned.

Example of calloc() in C

#include <stdio.h>
#include <stdlib.h>
int main()
{
    // This pointer will hold the base address of the block created
    int* ptr;
    int n, i;
    // Get the number of elements for the array
    n = 5;
    printf("Enter number of elements: %d\n", n);
    // Dynamically allocate memory using calloc()
    ptr = (int*)calloc(n, sizeof(int));
    // Check if the memory has been successfully
    // allocated by calloc or not
    if (ptr == NULL) {
        printf("Memory not allocated.\n");
        exit(0);
    }
    else {
        // Memory has been successfully allocated
        printf("Memory successfully allocated using calloc.\n");
        // Get the elements of the array
        for (i = 0; i < n; ++i) {
            ptr[i] = i + 1;
        }
        // Print the elements of the array
        printf("The elements of the array are: ");
        for (i = 0; i < n; ++i) {
            printf("%d, ", ptr[i]);
        }
    }
    return 0;
}

Output

Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,

3. C realloc() method

The realloc function in C is used to dynamically change the memory allocation of previously allocated memory. In other words, if the memory allocated with malloc() or calloc() is insufficient, realloc can be used to adjust the allocation. It keeps the existing values while any new blocks of memory will be initialized with garbage values.

Syntax of realloc() in C

(cast-type*) ptr = realloc(ptr, new-Size);
where ptr is reallocated with new size ‘new-Size’.

It can work with both malloc and calloc, the descriptive diagram is given below

If space is insufficient, allocation fails and returns a NULL pointer.

Note: Similar to malloc and calloc, if there is insufficient memory available when using realloc, the allocation will fail, and a NULL pointer will be returned.

Example Code of realloc() with malloc () 

malloc() with realloc() Dynamic Memory Allocation in C

#include <stdio.h>
#include <stdlib.h> // Required for malloc, calloc, realloc, and free
int main() {
    int n;
    printf("Enter the initial number of elements: ");
    scanf("%d", &n);
    // Using malloc to allocate memory
    int *array = (int *)malloc(n * sizeof(int));
    if (array == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }
    printf("Enter %d elements:\n", n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &array[i]);
    }
    printf("Initial Array Elements:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
    // Ask user if they want to add more elements
    int additional;
    printf("Do you want to add more elements? (Enter the number of additional elements): ");
    scanf("%d", &additional);
    // Resize the array using realloc
    int *temp = realloc(array, (n + additional) * sizeof(int));
    if (temp == NULL) {
        printf("Memory reallocation failed.\n");
        free(array); // Free the original array before exiting
        return 1;
    }
    array = temp; // Assign the new memory address
    // Input new elements
    printf("Enter %d additional elements:\n", additional);
    for (int i = n; i < n + additional; i++) {
        scanf("%d", &array[i]);
    }
    printf("Updated Array Elements:\n");
    for (int i = 0; i < n + additional; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
    // Free the allocated memory
    free(array);
    return 0;
}

Example Code of  calloc() with realloc()

Calloc() with realloc() Dynamic Memory Allocation in C

 #include <stdio.h>
#include <stdlib.h> // Required for malloc, calloc, realloc, and free
int main() {
    int n;
    printf("Enter the initial number of elements: ");
    scanf("%d", &n);
    // Using calloc to allocate memory and initialize to zero
    int *array = (int *)calloc(n, sizeof(int));
    if (array == NULL) {
        printf("Memory allocation failed.\n");
        return 1;
    }
    printf("Enter %d elements:\n", n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &array[i]);
    }
    printf("Initial Array Elements:\n");
    for (int i = 0; i < n; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
    // Ask user if they want to add more elements
    int additional;
    printf("Do you want to add more elements? (Enter the number of additional elements): ");
    scanf("%d", &additional);
    // Resize the array using realloc
    int *temp = realloc(array, (n + additional) * sizeof(int));
    if (temp == NULL) {
        printf("Memory reallocation failed.\n");
        free(array); // Free the original array before exiting
        return 1;
    }
    array = temp; // Assign the new memory address
    // Input new elements
    printf("Enter %d additional elements:\n", additional);
    for (int i = n; i < n + additional; i++) {
        scanf("%d", &array[i]);
    }
  printf("Updated Array Elements:\n");
  for (int i = 0; i < n + additional; i++) {
        printf("%d ", array[i]);
    }
    printf("\n"); 
// Free the allocated memory
    free(array);
    return 0;
}

C free() method

The free function in C is used to dynamically de-allocate memory. Memory allocated using malloc(), calloc(), and realloc() is not automatically freed, so the free() function must be called when the memory is no longer needed. This helps prevent memory wastage by releasing the allocated memory for reuse. Various examples are discussed in the earlier part of this lecture.

Syntax of free() in C

free(ptr);

When you use the free() function to de-allocate memory in C:

  • Memory is Released: The memory location is marked as available for future allocations.
  • Garbage Value: The contents of that memory location are still there, but you can no longer safely access it through the original pointer. The memory might contain old data (garbage) until it gets overwritten by a new allocation.
  • Null Pointer: After freeing the memory, it’s a good practice to set the pointer to NULL. This way, you avoid accidental dereferencing of a pointer that no longer points to valid memory.
free(ptr);
ptr = NULL; // Now ptr safely indicates that it points to nothing

So, even after freeing memory, the location itself is not empty; it still holds whatever data was there before it was freed, and setting the pointer to NULL helps prevent issues.

Note: Dereferencing a pointer means accessing the value that the pointer points through (*ptrName).

Important: Every memory location has a value (which could be garbage or a valid value), so it cannot truly be “empty.” It will always contain something, even meaningless or uninitialized data.