A Dynamically Growing Array is a dynamic data structure that automatically increases its size when it becomes full. It allows efficient storage of elements without requiring the size to be fixed at compile time.
- Unlike static arrays, its size is determined at runtime and can grow as more elements are added.
- It uses dynamic memory allocation (malloc() and realloc()) to allocate and resize memory whenever required.
- Since C does not provide built-in dynamic arrays, they must be implemented manually using pointers and dynamic memory management.
- The basic principle of the Dynamically Growing Array is the dynamic memory allocation which allow the users to allocate memory at runtime and also change the allocated size afterward.
Working

- A dynamic array is created with a small initial capacity to store the first few elements.
- Elements are inserted normally until the array becomes full.
- When the array reaches its capacity, realloc() is used to allocate a larger memory block.
- The array capacity is usually doubled to reduce the number of memory reallocations and improve performance.
- This resizing strategy keeps insertion efficient, providing an amortized time complexity of O(1) for insert operations.
- Once the array is no longer needed, the allocated memory is released using free() to prevent memory leaks.
Example: Program to create Dynamically Growing Arrays:
#include <stdio.h>
#include <stdlib.h>
#define INITIAL_SIZE 8
// base structure
typedef struct {
size_t size;
size_t capacity;
int* array;
}dynamic_array;
// function prototypes
// array container functions
void arrayInit(dynamic_array** arr_ptr);
void freeArray(dynamic_array* container);
// Basic Operation functions
void insertItem(dynamic_array* container, int item);
void updateItem(dynamic_array* container, int i, int item);
int getItem(dynamic_array* container, int i);
void deleteItem(dynamic_array* container, int item);
void printArray(dynamic_array* container);
int main()
{
dynamic_array* arr;
arrayInit(&arr);
for (int i = 0; i < 6; i++) {
insertItem(arr, i + 11);
}
printArray(arr);
for (int i = 0; i < 5; i++) {
insertItem(arr, i + 17);
}
printf("After Inserting 5 new Element\n");
printArray(arr);
freeArray(arr);
int var;
return 0;
}
//------Function Definitions------
// Array initialization
void arrayInit(dynamic_array** arr_ptr)
{
dynamic_array *container;
container = (dynamic_array*)malloc(sizeof(dynamic_array));
if(!container) {
printf("Memory Allocation Failed\n");
exit(0);
}
container->size = 0;
container->capacity = INITIAL_SIZE;
container->array = (int *)malloc(INITIAL_SIZE * sizeof(int));
if (!container->array){
printf("Memory Allocation Failed\n");
exit(0);
}
*arr_ptr = container;
}
// Insertion Operation
void insertItem(dynamic_array* container, int item)
{
if (container->size == container->capacity) {
int *temp = container->array;
container->capacity <<= 1;
container->array = realloc(container->array, container->capacity * sizeof(int));
if(!container->array) {
printf("Out of Memory\n");
container->array = temp;
return;
}
}
container->array[container->size++] = item;
}
// Retrieve Item at Particular Index
int getItem(dynamic_array* container, int index)
{
if(index >= container->size) {
printf("Index Out of Bounds\n");
return -1;
}
return container->array[index];
}
// Update Operation
void updateItem(dynamic_array* container, int index, int item)
{
if (index >= container->size) {
printf("Index Out of Bounds\n");
return;
}
container->array[index] = item;
}
// Delete Item from Particular Index
void deleteItem(dynamic_array* container, int index)
{
if(index >= container->size) {
printf("Index Out of Bounds\n");
return;
}
for (int i = index; i < container->size; i++) {
container->array[i] = container->array[i + 1];
}
container->size--;
}
// Array Traversal
void printArray(dynamic_array* container)
{
printf("Array elements: ");
for (int i = 0; i < container->size; i++) {
printf("%d ", container->array[i]);
}
printf("\nSize: ");
printf("%lu", container->size);
printf(", Capacity: ");
printf("%lu\n", container->capacity);
}
// Freeing the memory allocated to the array
void freeArray(dynamic_array* container)
{
free(container->array);
free(container);
}
Output
Array elements: 11 12 13 14 15 16 Size: 6, Capacity: 8 After Inserting 5 new Element Array elements: 11 12 13 14 15 16 17 18 19 20 21 Size: 11, Capacity: 16
Components of Dynamically Growing Array
A dynamically growing array consists of a few essential components that help manage data storage, resizing, and memory allocation efficiently.
1. dynamic_array
It is the name given to the structure type which serves as the container for our dynamically growing array. It contains 3 members:
- size: Counter to track the memory used.
- capacity: Counter to track the maximum capacity of the array.
- array: Pointer pointing to the actual storage location. (For this program, we will be using an array of type int)
typedef struct {
size_t size;
size_t capacity;
int* array;
} dynamic_array;
2. arrayInit()
This function initializes the dynamic array with the default initial size which is set to 8. This function takes the address of the double-pointer to the dynamic_array pointer as an argument.
void arrayInit(dynamic_array** arr_ptr)
{
dynamic_array *container;
container = (dynamic_array*)malloc(sizeof(dynamic_array));
if(!container) {
printf("Memory Allocation Failed\n");
exit(0);
}
container->size = 0;
container->capacity = INITIAL_SIZE;
container->array = (int *)malloc(INITIAL_SIZE * sizeof(int));
if (!container->array){
printf("Memory Allocation Failed\n");
exit(0);
}
*arr_ptr = container;
}
3. freeArray()
This function frees the memory allocated to the dynamically growing array. This function should be called after we are done using the array.
void freeArray(dynamic_array* container)
{
free(container->array);
free(container);
}
Rest components are the functions providing basic array operations for our Dynamically Growing Array. They are discussed below:
Basic Operations
There are 5 functions that provide the basic operations of an array which are as follows:
1. insertItem()
The insertItem() function inserts a new element into the dynamic array and resizes it when required.
- Inserts the element directly if space is available.
- Doubles the array size using realloc() when the array becomes full.
void insertItem(dynamic_array* container, int item)
{
if (container->size == container->capacity) {
int *temp = container->array;
container->capacity <<= 1;
container->array = realloc(container->array, container->capacity * sizeof(int));
if(!container->array) {
printf("Out of Memory\n");
container->array = temp;
return;
}
}
container->array[container->size++] = item;
}
2. getItem()
This function returns the integer value present at the given index. It takes two arguments - container address and index.
int getItem(dynamic_array* container, int index)
{
if(index > container->size) {
printf("Index Out of Bounds\n");
return -1;
}
return container->array[index];
}
3. updateItem()
The updateItem() function facilitates us to update the element present at a particular index. This function take 3 arguments - container address, index, and updated_item.
void updateItem(dynamic_array* container, int index, int item)
{
if (index > container->size) {
printf("Index Out of Bounds\n");
return;
}
container->array[index] = item;
}
4. printItem()
This function traverses the array and prints all the elements. Apart from that, it also prints the current size and capacity of the array.
void printArray(dynamic_array* container)
{
printf("Array elements: ");
for (int i = 0; i < container->size; i++) {
printf("%d ", container->array[i]);
}
printf("\nSize: ");
printf("%ld", container->size);
printf("\nCapacity: ");
printf("%ld\n", container->capacity);
}
5. deleteItem()
The deleteItem() function provides the deletion operation using which we can remove the element at any particular index.
void deleteItem(dynamic_array* container, int index)
{
if(index > container->size) {
printf("Index Out of Bounds\n");
return;
}
for (int i = index; i < container->size; i++) {
container->array[i] = container->array[i + 1];
}
container->size--;
}