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.
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.
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 ()
#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()
#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.