A two-dimensional array can be allocated dynamically when its dimensions are determined at runtime. One approach is to allocate a contiguous block of memory for all elements and access them using calculated row and column offsets.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t rows = 2;
size_t cols = 3;
int *matrix = malloc(rows * cols * sizeof(*matrix));
if (matrix == NULL)
{
printf("Memory allocation failed\n");
return 1;
}
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < cols; j++)
{
matrix[i * cols + j] = (int)(i * cols + j + 1);
}
}
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < cols; j++)
{
printf("%d ", matrix[i * cols + j]);
}
printf("\n");
}
free(matrix);
return 0;
}
Example Output #
1 2 3
4 5 6
Explanation #
The allocation:
int *matrix = malloc(rows * cols * sizeof(*matrix));
requests enough memory for rows * cols integers. The returned pointer refers to the first element of the allocated block.
The expression:
matrix[i * cols + j]
maps a row and column to a single index in row-major order. For example, in a three-column matrix, matrix[1 * 3 + 2] accesses the element in the second row and third column.
The allocation must be checked before accessing the memory. Once the elements are no longer needed, free(matrix) releases the allocated storage.
Dynamic Allocation Approaches #
| Approach | Description |
|---|---|
| Contiguous allocation | One memory block stores all elements |
| Array of row pointers | Each row is allocated separately |
| Pointer to a variable-length array | A pointer provides two-dimensional indexing when the dimensions are known at runtime and the implementation supports variable-length arrays |
For a contiguous allocation, the requested element count and byte size must not overflow size_t. For example, validate the dimensions before calculating rows * cols * sizeof(*matrix) when dimensions come from external input.
This implementation provides contiguous storage, predictable row-major layout, and a single allocation to release.