Dynamic Memory Allocation In C Using Malloc(), Calloc(), Free() And Realloc()

Dynamic Memory Allocation In C Using Malloc(), Calloc(), Free() And Realloc()

Dynamic memory allocation is a fundamental concept in the C programming language that allows developers to efficiently manage memory resources during runtime. Unlike static memory allocation, which defines memory usage at compile time, dynamic memory allocation enables programs to request and release memory as needed. This flexibility is particularly valuable when working with data structures of varying sizes or when you need to allocate memory for data structures whose size is not known until runtime. In C, this dynamic memory allocation is achieved through functions like malloc(), calloc(), free(), and realloc(). These functions provide the means to allocate memory, initialize it, release it, and even resize it, empowering programmers to optimize memory usage in their applications. This introductory guide will explore the usage of these functions, offering insights into how to harness their power for efficient memory management in C programming.

Dynamic Memory Allocation in C

Dynamic memory allocation is a fundamental concept that allows developers to adapt the size of data structures, such as arrays, during program execution. This adaptability is especially crucial when the actual size of the data structure cannot be determined at compile time or when it needs to change dynamically based on program requirements.

The four library functions provided by C, namely malloc(), calloc(), free(), and realloc(), are key tools for implementing dynamic memory allocation. They empower programmers to allocate memory, initialize it, release it when no longer needed, and resize data structures, ensuring the efficient use of memory resources.

Dynamic memory allocation is a powerful feature that enhances the flexibility and efficiency of C programming, enabling developers to create more adaptable and resource-efficient applications. It is particularly valuable in scenarios like the ones you’ve described, where the size of an array needs to be adjusted at runtime to prevent memory wastage or accommodate additional data.

C malloc() method

  1. Dynamic Memory Allocation: The malloc function in C is used to dynamically allocate a single large block of memory during runtime. This memory allocation is done based on the specified size provided as an argument to malloc.
  2. Pointer Return Type: malloc returns a pointer of type void, which means it can be cast into a pointer of any data type. Programmers typically cast this void pointer into the appropriate data type pointer to work with the allocated memory.
  3. Uninitialized Memory: One crucial aspect of malloc is that it does not initialize the memory it allocates. The memory block initially contains garbage values, which means the content of the allocated memory is indeterminate until you explicitly write values into it. It’s important for programmers to initialize the memory if necessary to avoid unexpected behavior in their programs.

This function is widely used for dynamic memory allocation in C and is the first step in allocating memory for various data structures, such as arrays, linked lists, and more. To ensure predictable behavior, it’s essential to initialize the allocated memory to the desired values before using it in your program.

Syntax of malloc() in C

ptr = (cast-type*) malloc(byte-size)
For Example:
ptr = (int*) malloc(100 * sizeof(int));
Due  the size of int is 4 bytes, this statement will allocate 400 bytes of memory. Thus, the pointer ptr holds the address of the first byte in the allocated memory.

Example of malloc() 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
    printf("Enter number of elements:");
    scanf("%d",&n);
    printf("Entered number of elements: %d\n", n);
 
    // Dynamically allocate memory using malloc()
    ptr = (int*)malloc(n * sizeof(int));
 
    // Check if the memory has been successfully
    // allocated by malloc or not
    if (ptr == NULL) {
        printf("Memory not allocated.\n");
        exit(0);
    }
    else {
 // Memory has been successfully allocated
        printf("Memory successfully allocated using malloc.\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 malloc.
The elements of the array are: 1, 2, 3, 4, 5,

C calloc() method

  1. Dynamic Memory Allocation: The calloc function in C is used for dynamic memory allocation, much like the malloc function. It allows you to allocate memory for a specified number of blocks of a specified type during program execution.
  2. Initialization to Zero: One significant difference between calloc and malloc is that calloc initializes each block of memory with a default value of ‘0’. This means that the memory allocated by calloc is set to zeros by default. This can be useful when you want to ensure that the allocated memory starts with a known initial state.
  3. Two Parameters: calloc takes two parameters or arguments: the number of blocks you want to allocate and the size of each block in bytes. In contrast, malloc typically takes a single argument, which is the total size of memory to allocate.

calloc is often used when you want to allocate and initialize an array of elements, and you want to ensure that all elements start with a default value of zero. This can be helpful in scenarios where you need to work with arrays or matrices and want to avoid any unpredictable values in the allocated memory.

So, while calloc and malloc serve the same general purpose of dynamic memory allocation, they differ in their behavior regarding memory initialization and the number of parameters they accept.

Syntax of calloc() in C

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

Example

ptr = (float*) calloc(25, sizeof(float));
This statement can allocate acontiguous space in memory for 25 elements whereas, each element with the size of the float. 

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,

C free() method

  1. Dynamic Memory Deallocation: The free function in C is used to dynamically deallocate (release) memory that was previously allocated using functions like malloc and calloc.
  2. Manual Memory Management: Memory allocated using malloc and calloc is not automatically deallocated by the program; it remains allocated until explicitly released. This manual memory management is a fundamental responsibility of the programmer.
  3. Wastage Reduction: One of the primary purposes of the free function is to reduce memory wastage. By releasing memory that is no longer needed, the program can make efficient use of available memory resources.

It’s important to note that not properly freeing memory can lead to memory leaks, where memory is allocated but never released, causing the program’s memory consumption to grow over time. Therefore, it’s a good practice to use free to release memory as soon as it is no longer required within your program to ensure efficient memory management.

Syntax of free() in C

free(ptr);

Example of free() in C

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
 
    // This pointer will hold the
    // base address of the block created
    int *ptr, *ptr1;
    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 malloc()
    ptr = (int*)malloc(n * sizeof(int));
 
    // Dynamically allocate memory using calloc()
    ptr1 = (int*)calloc(n, sizeof(int));
 
    // Check if the memory has been successfully
    // allocated by malloc or not
    if (ptr == NULL || ptr1 == NULL) {
        printf("Memory not allocated.\n");
        exit(0);
    }
    else {
 
        // Memory has been successfully allocated
        printf("Memory successfully allocated using malloc.\n");
 
        // Free the memory
        free(ptr);
        printf("Malloc Memory successfully freed.\n");
 
        // Memory has been successfully allocated
        printf("\nMemory successfully allocated using calloc.\n");
 
        // Free the memory
        free(ptr1);
        printf("Calloc Memory successfully freed.\n");
    }
 
    return 0;
}

Output

Enter number of elements: 5
Memory successfully allocated using malloc.
Malloc Memory successfully freed.

Memory successfully allocated using calloc.
Calloc Memory successfully freed.

C realloc() method

  1. Dynamic Memory Reallocation: The realloc function in C is used to dynamically change the memory allocation of a previously allocated memory block. This allows you to resize the memory block allocated by malloc or calloc during runtime.
  2. Insufficient Memory: realloc is particularly useful when the previously allocated memory is insufficient to hold the data or elements you want to store. It enables you to increase or decrease the size of the memory block to accommodate the new requirements.
  3. Data Preservation: When you use realloc to increase the size of the memory block, it preserves the data that is already present in the existing memory. In other words, the data from the original memory block is retained in the new, larger memory block. However, any newly allocated memory within the resized block will contain garbage values unless explicitly initialized.
  4. Efficient Memory Usage: realloc helps in efficient memory usage by allowing you to adapt the memory allocation to your program’s needs without unnecessary memory wastage or the risk of buffer overflows.

Overall, realloc is a powerful tool for managing memory efficiently in C programs, as it gives you the flexibility to adjust memory sizes dynamically to meet changing requirements while retaining existing data.

Syntax of realloc() in C

ptr = realloc(ptr, newSize);
where ptr is reallocated with new size 'newSize'.

Example of realloc() 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 malloc 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]);
        }
 
        // Get the new size for the array
        n = 10;
        printf("\n\nEnter the new size of the array: %d\n", n);
 
        // Dynamically re-allocate memory using realloc()
        ptr = (int*)realloc(ptr, n * sizeof(int));
 
        // Memory has been successfully allocated
        printf("Memory successfully re-allocated using realloc.\n");
 
        // Get the new elements of the array
        for (i = 5; 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]);
        }
 
        free(ptr);
    }
 
    return 0;
}

Output

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

Enter the new size of the array: 10
Memory successfully re-allocated using realloc.
The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

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

Q1. What is dynamic memory allocation malloc and calloc in C?

Ans. malloc() and calloc() are C functions for dynamic memory allocation.
The key difference is that malloc() requires one argument for the total memory size and leaves it uninitialized, while calloc() needs two arguments: the number of elements and their size, and it initializes the memory to zero.

Q2. Under which header file are dynamic memory allocation functions such as calloc malloc realloc and free provided?

Ans. To allocate memory dynamically in C, you can use library functions like malloc(), calloc(), realloc(), and free(). These functions are part of the <stdlib.h> header file.

Q3. What is better calloc and malloc?

Ans.
calloc() zero-initializes memory, good for when initialization is crucial, with a minor performance cost.
malloc() leaves memory uninitialized, faster if performance matters and initialization isn’t needed.
calloc() can save you from calling memset() to zero out memory.

Hridhya Manoj

Hello, I’m Hridhya Manoj. I’m passionate about technology and its ever-evolving landscape. With a deep love for writing and a curious mind, I enjoy translating complex concepts into understandable, engaging content. Let’s explore the world of tech together

Leave a Comment