Dynamic memory allocation in C programming

Dynamic memory allocation refers to the process of manual memory management (allocation and deallocation). Dynamic memory allocation in C is performed via a group of built-in functions malloc(), calloc(), realloc() and free(). Some text also refer Dynamic memory allocation as Runtime memory allocation.

We have discussed in one of previous article about Compile time and Runtime memory allocation. C supports two ways to allocate memory for the variables used in the program. Here in this article I will explain about Dynamic Memory Allocation in C programming language.

Before getting our hands dirty with managing memory manually. Let us first learn the need for dynamic memory allocation in C.

Need of Dynamic Memory Allocation in C?

  • We must know the exact size of memory required for static memory allocation, since its allocated during the compilation process. Dynamic memory allocation allocates memory at runtime, hence its more flexible.
  • With Dynamic Memory Allocation in C, you can reallocate (extend or shrink) memory at run time.
  • C programming language does not have its garbage collector (used to clear unused memory automatically) or related concept. Dynamic memory management allows to free/release unused memory at runtime.
  • We can allocate and deallocate memory at runtime as per need. Hence, we will always have exact amount of memory required.
  • With static memory allocation it is impossible to create memory for big arrays. With dynamic memory allocation we can allocate as much memory required for our program.

In C programming language, we will use four functions to manage memory (allocate, reallocate and free). These functions are declared in stdlib.h header file.

Functions for Dynamic Memory Allocation in C

  1. malloc()
  2. calloc()
  3. realloc()
  4. free()

To use these function, you must include stdlib.h header file.

malloc() function

malloc() allocates N bytes in memory and return pointer to allocated memory. The returned pointer contains link/handle to the allocated memory. Using that you can access the memory allocated.

Syntax

void * malloc(number_of_bytes);

Note: malloc() returns NULL pointer on failure.

Example

int N = 10; // Number of bytes to allocate
int *ptr;   // Pointer variable to store address

ptr = (int *) malloc(N * sizeof(int));  // Allocate 10 * 4 bytes in memory

The above statement will allocate 10 * 4 bytes (if size of integer is 4 bytes).

Here,

  • ptr is a pointer to integer to store address of the allocated memory.
  • (int *) is typecast required. As, I mentioned above that malloc() return void *. Hence, to work with void pointer we must typecast it to suitable type.
  • N * sizeof(int) – Since size of int is not fixed on all compilers. Hence, to get size of integer on current compiler I have used sizeof() operator.

Some more examples to allocate memory using malloc() function.

// Allocate memory for N integers
int N = 10;
int *ptr;
ptr = (int *) malloc (N * sizeof(int));

// Allocate memory for 50 characters or string of length 50
char *name;
name = (char *) malloc(50 * sizeof(char));

// Allocate memory for 10 records of student structure type
struct student *stdList;
stdList = (struct student *) malloc(10 * sizeof(struct student));

Program to demonstrate malloc() function

Write a program to read and print integer array. The program should input total number of elements (limit) and elements in array from user. Use dynamic memory allocation to allocate and deallocate array memory.

/**
 * C program to demonstrate malloc() and free() function.
 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, max;
    int *ptr;

    // Input maximum elements of array
    printf("Enter total number of elements: ");
    scanf("%d", &max);
    
    // Allocate memory for 'max' integer elements 
    ptr = (int *) malloc(max * sizeof(int));
    
    // If memory not allocated
    if(ptr == NULL)
    {
        printf("Memory is not created!!!");
        exit(0); // Exit from the program
    }
    
    // Input elements from user
    printf("Enter %d elements: \n", max);
    for (i = 0; i < max; i++)
        scanf("%d", (ptr + i));
    
    // Print all elements 
    printf("\nArray elements are:\n");
    for (i = 0; i < max; i++)
        printf("%d ", *(ptr + i));
    
    // Release allocated memory
    free(ptr);
    
    return 0;
}

Note: I will discuss about free() function at the end of this article.

Output:

Enter total number of elements: 5
Enter 5 elements:
10 20 30 40 50

Array elements are:
10 20 30 40 50

calloc() function

calloc() function allocates memory contiguously. It allocates multiple memory blocks and initializes all blocks with 0 (NULL).

Note: malloc() allocates uninitialized memory blocks.

Syntax

void* calloc(number_of_blocks, number_of_bytes);

Here,

  • Similar to malloc() it returns void pointer.
  • It accepts two parameters number_of_blocks i.e. total blocks to allocate and number_of_bytes i.e. bytes to allocate per block.

    Therefore, you can say that calloc() will allocate total (number_of_blocks * number_of_bytes) bytes. Each block initialized with 0 (NULL).

Example

Similar to malloc() function, we can also use calloc() to reserve memory for N integers.

int *ptr;
ptr = (int *) calloc(N, sizeof(int));

Here, all memory blocks are initialized with 0.

Program to demonstrate calloc() function

Write a C program to read and print integer array. The program should input total number of elements (limit) and elements in array from user. The program must manage memory allocation and deallocation dynamically.

Note: Below program is same as malloc() function program. Only the way to allocate memory is different for calloc() i.e. ptr = (int*) calloc(max, sizeof(int));.

/**
 * C program to demonstrate calloc() and free() function.
 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, max;
    int *ptr;

    // Input maximum elements of array
    printf("Enter total number of elements: ");
    scanf("%d", &max);
    
    // Allocate memory for 'max' integer elements 
    ptr = (int *) calloc(max, sizeof(int));
    
    // If memory not allocated
    if(ptr == NULL)
    {
        printf("Memory is not created!!!");
        exit(0); // Exit from the program
    }
    
    // Input elements from user
    printf("Enter %d elements: \n", max);
    for (i = 0; i < max; i++)
        scanf("%d", (ptr + i));
    
    // Print all elements 
    printf("\nArray elements are:\n");
    for (i = 0; i < max; i++)
        printf("%d ", *(ptr + i));
    
    // Release allocated memory
    free(ptr);
    
    return 0;
}

Output:

Enter total number of elements: 5
Enter 5 elements:
10 20 30 40 50

Array elements are:
10 20 30 40 50

realloc() function

When working with huge data and if the allocated memory is not sufficient to store data. In that case, we need to alter/update the size of an existing allocated memory blocks (which has been created by either malloc() or calloc()).

We use realloc() function to alter/update the size of exiting allocated memory blocks. The function may resize or move the allocated memory blocks to a new location.

Syntax

void* realloc(ptr, updated_memory_size);
  • Similar to all other functions for Dynamic Memory Allocation in C, it returns void pointer. Which points to the address of existing or newly allocated memory.
  • ptr is a pointer to memory block of previously allocated memory.
  • updated_memory_size is new (existing + new) size of the memory block.

Facts about realloc() function

  • realloc() function may or may not allocate new memory blocks at the same location.
  • The function will move data from old location to new location, if memory allocated at new location. Hence, it ensure no data loss.
  • realloc() return NULL pointer on failure and releases original memory blocks.

Example

// Original memory blocks allocation
int N = 10;
int *ptr;
ptr = (int *) malloc(N * sizeof(int));

// Increase the value of N
N = 50;
// Reallocate memory blocks
ptr = (int *) realloc(ptr, N * sizeof(int));

Program to demonstrate realloc() function

/**
 * C program to demonstrate ralloc() and free() function.
 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, max, newSize;
    int *ptr;

    // Input maximum elements of array
    printf("Enter total number of elements: ");
    scanf("%d", &max);
    
    // Allocate memory for 'max' integer elements using calloc
    ptr = (int *) calloc(max, sizeof(int));
    
    // If memory not allocated
    if(ptr == NULL)
    {
        printf("Memory is not created!!!");
        exit(0); // Exit from the program
    }
    
    // Input elements from user
    printf("Enter %d elements: \n", max);
    for (i = 0; i < max; i++)
        scanf("%d", (ptr + i));

    // Reallocate memory 
    printf("\nEnter new size of the array: ");
    scanf("%d", &newSize);
    ptr = (int *) realloc(ptr, (newSize * sizeof(int)));

    
    // Input elements in newly allocated memory
    printf("\nEnter %d elements: \n", (newSize - max));
    for (i = max; i < newSize; i++)
        scanf("%d", (ptr + i));
    
    // Print all elements 
    printf("\nArray elements are:\n");
    for (i = 0; i < newSize; i++)
        printf("%d ", *(ptr + i));
    
    // Release allocated memory
    free(ptr);
    
    return 0;
}

Output:

Enter total number of elements: 5
Enter 5 elements:
10 20 30 40 50

Enter new size of the array: 7

Enter 2 elements: 60 70

Array elements are:
10 20 30 40 50 60 70

free() function

Till now we learned to allocate and reallocate memory in C. But moreover allocation, how to clear allocated memory is important.

C programming has a built-in library function free() to clear or release the unused memory.

The free() function clears the pointer (assigns NULL to the pointer) to clear the dynamically allocated memory. If pointer contains NULL, then free() does nothing (because pointer will not be pointing at any memory addresses). If it contains any address of dynamically allocated memory, free() will clear pointer by assigning NULL.

Syntax

free(ptr);

The function accepts a void pointer ptr. It points to previously allocated memory using any of Dynamic Memory Allocation functions in C.

Example

int N = 10;
int *ptr;

// Allocate memory using malloc
ptr = (int *) malloc(N * sizeof(int));

// Free allocated memory
free(ptr);

Wrapping up things, we have learned how to manage memory manually in C. We use four functions malloc(), calloc(), realloc() and free() to perform Dynamic Memory Allocation in C programming language. These functions are defined in stdlib.h header file.

Have, any doubt or feedback please drop down in comments section.

Happy coding 😉