When we’re working with arrays, we’ll often run into a situation where we need to adjust the size of the array. This could be increasing its size to add more elements, or decreasing its size to eliminate empty indices to save memory. This is where the concept of dynamic memory allocation comes into play. Read on for an overview of how this works and how to implement it in C.
What Is Dynamic Memory Allocation and Why Is It Important?
As briefly mentioned, dynamic memory allocation is the process of changing array size. This can be done with string arrays, but is mostly used with integer arrays. The helpful part about this is that it’s done during the runtime of the program. While called allocation, the process involves deallocating memory as well. This allows the program to request these changes as needed. Sometimes, we don’t know exactly how much memory we’ll need before we run a program. Dynamic memory allocation becomes very useful in this case.
Generally, dynamic memory allocation is in contrast to static memory allocation. As you may have guessed, static allocation cannot change the array size during runtime, only doing it at the time of compiling. Static allocation can also only be used for arrays, whereas dynamic allocation can be used for linked lists as well as tree structures.
What Types of Dynamic Memory Allocation Are There?
There are two main types of dynamic memory allocation – heap-based, and stack-based.
As the names suggest, heap-based uses memory allocated to a heap structure, while stack-based concerns memory allocated to a stack. Heap-based is a very common usage, such as for the structures previously mentioned, as well as hash tables. Stack-based, however, is generally used to allocate memory for functions, as well as construct temporary variables.
Although many programming languages can use manual memory allocation, some have a built-in function known as a “garbage collector” for automatically allocating memory. These include Python, Ruby and Java.
The Working Behind Dynamic Memory Allocation Functions
There are four functions used for dynamic memory allocation — malloc(), calloc(), free(), and realloc(). It’s time to jump into these and discover what they’re all about.
Malloc()
Standing for “memory allocation”, malloc() would be used when you need to allocate just one memory block to the program. A pointer is assigned which points to the first block of available memory. If the memory isn’t sufficient for this, a NULL value is returned by the function. The syntax of the function is given below.
void* malloc(size_t size);
where “void*” is a void type pointer, “malloc()” is the malloc() function, and “size” is the number of bytes of memory allocated.
Here is the code for malloc() implemented in C:
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
int* ptr;
printf("Enter the size of the dynamic array: ");
scanf("%d", &num);
ptr = (int*)malloc(num * sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
for (int i = 0; i < num; i++) {
printf("Enter element %d: ", i + 1);
scanf("%d", &ptr[i]);
}
printf("The dynamic array is: ");
for (int i = 0; i < num; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
return 0;
}
Explanation of Code
First, we use include statements to include the standard library and input/output files. Then, we declare the “main()” function as the program’s entry point. Two variables are then declared — the integer “n”, the array size, and a pointer “arr”, used to point to the array.
After this, the user is prompted to enter the array size, and the value is read into “n.”
Next, we allocate memory to the array using the “malloc()” function. Bytes equivalent to “N * sizeof(int)” are allocated, and a pointer is returned that points to the first block. “(int*)” is used to convert the pointer to an integer value.
The next block of code checks if the allocation was successful. If the allocation returns NULL, it’s considered as failed as a value of 1 is returned.
The “for” loop next reads the elements and stores them in the array. The results of the allocation are then printed.
The final statement returns 0 after ending the “main” function. The results can be seen below, with element values entered as 4, 6, 8, 10 and 12.

©History-Computer.com
Calloc()
Calloc() is named as such as it’s short for contiguous memory allocation. While malloc() also allocates a continuous memory block, calloc() differs in that the memory allocated is initialized to 0. This is useful when dealing with sensitive data, such as passwords. Initializing to 0 ensures that no garbage data values are included which could compromise security. Calloc() is also helpful to save time when you don’t want to have to initialize each data field manually. The syntax for calloc() is as follows:
int* arr = (int*)calloc(5, sizeof(int));
where “int*” is the type of pointer value of the variable “arr.” “calloc()” is the calloc() function being declared, taking the number of elements argument and the size of each element. Namely, “5” is the element number and “sizeof(int)” is the size of each in bytes.
To implement calloc() in C, we can use the following code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* mem_block;
int num_elements, i;
num_elements = 5;
printf("Enter number of elements: %d\n", num_elements);
mem_block = (int*)calloc(num_elements, sizeof(int));
if (mem_block == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
printf("Memory successfully allocated using calloc.\n");
for (i = 0; i < num_elements; ++i) {
mem_block[i] = i + 1;
}
printf("The elements of the array are: ");
for (i = 0; i < num_elements; ++i) {
printf("%d, ", mem_block[i]);
}
}
return 0;
}
Explanation of Code
As before, we include the standard header files. Then, we declare a “mem_block” pointer that stores the address of the allocated block, and the variables “i” and “num_elements.” After, we set the number of array elements to 5, which is then printed.
Memory is then allocated using “calloc()”, and the results stored in the pointer mentioned before. This is then checked, and, if failed, returns a status of 0. If successful, a verification message is printed. Each element is initialized using the counter variable “i”, so that the first element is set to 1, the second to 2, etc.
To finish, each element’s value is printed, and 0 is returned upon completion. The image below shows this code in action.

©History-Computer.com
Free()
Free() is a function used to deallocate memory, because the previous functions don’t do this automatically. To reduce memory wastage, using free() is usually essential. Free() has the following syntax:
void free(void* ptr);
where “ptr” is a pointer directed to the allocated block, “void” indicates that “free()” doesn’t return a value, and “void*” is the data of the pointer parameter.
To implement free() in C, we can use this code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr, *ptr1;
int num_elements, i;
num_elements = 5;
printf("Enter number of elements: %d\n", num_elements);
ptr = (int*)malloc(num_elements * sizeof(int));
ptr1 = (int*)calloc(num_elements, sizeof(int));
if (ptr == NULL || ptr1 == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
printf("Memory successfully allocated using malloc.\n");
free(ptr);
printf("Memory successfully freed.\n");
printf("\nMemory successfully allocated using calloc.\n");
free(ptr1);
printf("Memory successfully freed.\n");
}
return 0;
}
Explanation of Code
We include the standard header files again, then we declare the pointer variable and integer variables. Then, the number of elements is read and printed, and memory is allocated using “malloc.” An “if” statement is used to check if the memory allocation was successful, and a message is printed if it failed. “n” integers are then stored in the allocated block and printed, at which point the memory is freed using the “free()” function.
More memory is allocated using “calloc()”, with the bytes initialized to 0. This operation is checked for success as before, and, if all was successful, success messages are printed using the “else” statement, and the program terminated. This is shown in the image below.

©History-Computer.com
Realloc()
Realloc() is another function used for memory allocation, but this function is used to change, or “reallocate”, memory that was previously allocated. This is mostly used when the memory that was allocated is insufficient for the use case. The syntax for realloc() is:
void *realloc(void *ptr, size_t size);
where “ptr” is a pointer, “size” is the new size in bytes, “realloc()” is the realloc() function. “Void’ indicates no value is returned.
To implement realloc() in C, we can use the code below.
#include <stdio.h>
#include <stdlib.h>
int main() {
int* arr;
int size, i;
size = 5;
printf("Enter initial size of the array: %d\n", size);
arr = calloc(size, sizeof(int));
if (arr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
else {
printf("Memory successfully allocated using calloc.\n");
for (i = 0; i < size; ++i) {
arr[i] = i + 1;
}
printf("The elements of the array are: ");
for (i = 0; i < size; ++i) {
printf("%d, ", arr[i]);
}
size = 10;
printf("\nEnter the new size of the array: %d\n", size);
arr = realloc(arr, size * sizeof(int));
printf("Memory successfully re-allocated using realloc.\n");
for (i = 5; i < size; ++i) {
arr[i] = i + 1;
}
printf("The elements of the array are: ");
for (i = 0; i < size; ++i) {
printf("%d, ", arr[i]);
}
free(arr);
}
return 0;
}
Explanation of Code
The standard header files are included, and the “main()” function is declared. The pointer variable is also declared, along with the “n” and “i” integer variables. “n” is initialized to 5, and the user is prompted to enter the number of elements here.
Memory is allocated using “calloc()”, and an “if” statement checks whether this was successful. Corresponding messages are printed to the console.
If the allocation was successful, as per the “else” statement, a “for” loop is used to traverse the array, assigning values to the ith element as it goes with “ptr[i] = i + 1.”
The next code block has another “for” loop, which prints the values of each element in the allocated memory block.
Then, the value of “n” is changed to 10, the memory is reallocated using “realloc()” and the new results are printed along with a success message.
Finally, the memory is freed using “free()”, and the program is terminated. This is all shown in the screenshots below.

©History-Computer.com

©History-Computer.com
Dynamic Memory Allocation: Wrapping Up
Overall, memory allocation functions are essential when manually allocating memory in languages that don’t have automatic garbage collection functions. Being able to dynamically change memory allocation during runtime is useful when the required memory is unknown, or memory is restricted and we need to free up as much as possible. To code efficiently, memory allocation is a very helpful tool in your arsenal.
The image featured at the top of this post is ©StockEU/Shutterstock.com.