Dynamic Memory Allocation in C: Mastering malloc, calloc, realloc, and free
Dynamic Memory Allocation in C
This guide walks you through dynamic memory allocation in C using the standard library functions malloc(), calloc(), realloc(), and free(), with clear examples and best‑practice tips.
Why Use Dynamic Allocation?
Static arrays have a fixed size declared at compile time, which can lead to wasted space or insufficient capacity during runtime. Dynamic allocation lets you request exactly the amount of memory you need while the program is running.
All four functions are defined in the <stdlib.h> header and provide a controlled way to manage heap memory.
malloc() – Allocate a Block of Bytes
The name malloc stands for "memory allocation." It reserves a contiguous block of memory of the specified size (in bytes) and returns a pointer of type void * that can be cast to any other pointer type.
Syntax
ptr = malloc(size_in_bytes); // cast to desired type if needed
Example
float *ptr = malloc(100 * sizeof(float)); // 400 bytes on most systems
Here, ptr points to the first byte of a 400‑byte block. If the request fails, malloc returns NULL.
It is recommended to avoid unnecessary casts in C; the compiler can deduce the type when you assign the result to a typed pointer.
calloc() – Allocate and Zero‑Initialize
calloc stands for "contiguous allocation." Unlike malloc, it initializes every bit of the allocated block to zero, making it safe for numeric types and pointers.
Syntax
ptr = calloc(num_elements, size_of_each_element);
Example
float *ptr = calloc(25, sizeof(float)); // 25 zeroed float elements
The returned pointer is NULL if the allocation fails.
free() – Release Allocated Memory
Memory obtained with malloc or calloc persists until you explicitly release it. free() deallocates the block and returns the memory to the heap for future reuse.
Syntax
free(ptr);
Calling free on a NULL pointer is safe and does nothing.
Example 1: Using malloc() and free()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = malloc(n * sizeof(int));
if (!ptr) {
fprintf(stderr, "Error: memory not allocated.\n");
return EXIT_FAILURE;
}
printf("Enter elements: ");
for (i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum += *(ptr + i);
}
printf("Sum = %d\n", sum);
free(ptr);
return EXIT_SUCCESS;
}
Output
Enter number of elements: 3
Enter elements: 100 20 36
Sum = 156
Example 2: Using calloc() and free()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i, *ptr, sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
ptr = calloc(n, sizeof(int));
if (!ptr) {
fprintf(stderr, "Error: memory not allocated.\n");
return EXIT_FAILURE;
}
printf("Enter elements: ");
for (i = 0; i < n; ++i) {
scanf("%d", ptr + i);
sum += *(ptr + i);
}
printf("Sum = %d\n", sum);
free(ptr);
return EXIT_SUCCESS;
}
Output
Enter number of elements: 3
Enter elements: 100 20 36
Sum = 156
realloc() – Resize an Existing Allocation
If you discover that your current allocation is too small or larger than needed, realloc() adjusts the size while preserving the existing data (up to the new size).
Syntax
ptr = realloc(ptr, new_size_in_bytes);
It returns a pointer to the reallocated block or NULL on failure. To avoid memory leaks, store the result in a temporary pointer first.
Example 3: Using realloc()
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *ptr, i, n1, n2;
printf("Enter initial size: ");
scanf("%d", &n1);
ptr = malloc(n1 * sizeof(int));
if (!ptr) {
fprintf(stderr, "Allocation failed.\n");
return EXIT_FAILURE;
}
printf("Addresses before reallocation:\n");
for (i = 0; i < n1; ++i)
printf("%p\n", ptr + i);
printf("\nEnter new size: ");
scanf("%d", &n2);
int *tmp = realloc(ptr, n2 * sizeof(int));
if (!tmp) {
fprintf(stderr, "Reallocation failed.\n");
free(ptr);
return EXIT_FAILURE;
}
ptr = tmp;
printf("Addresses after reallocation:\n");
for (i = 0; i < n2; ++i)
printf("%p\n", ptr + i);
free(ptr);
return EXIT_SUCCESS;
}
Typical Output
Enter initial size: 2
Addresses before reallocation:
0x7ffc12345670
0x7ffc12345674
Enter new size: 4
Addresses after reallocation:
0x7ffc12345670
0x7ffc12345674
0x7ffc12345678
0x7ffc1234567c
By mastering these four functions and applying proper error handling, you can manage heap memory safely and efficiently in any C application.
C Language
- Understanding ROM, PROM, EPROM, and EEPROM: Design, Programming, and Identification
- Understanding Look‑Up Tables: From ROMs to Advanced ALUs
- Microprocessors: The Evolution of Stored‑Program Computing
- Master C++ Dynamic Array Allocation: A Practical Guide with Code Examples
- Dynamic Memory Allocation in C: Mastering malloc, calloc, realloc, and free
- Java Stack vs. Heap: A Practical Memory Allocation Guide
- Dynamic Memory Management in C: calloc, malloc, and free Explained
- Mastering C++ Dynamic Memory: Stack vs. Heap Explained
- Java 10 Enhancements: Allocate Heap on NV‑DIMM with -XX:AllocateHeapAt
- G.AL® C330 Dynamic: High-Strength Aluminum Alloy for Precision Applications