Instead of creating a single 1-D array and treating it as a 2-D array, you could create a 1-D array of pointers, where each pointer points to another 1-D array. This lets you allocate each row in the array with a different size.
For example:
// Allocate and initialize a triangular 2-D array
int** make_triangle_array(int nrows)
{
int ** arr;
// Allocate the 1-D array of pointers
arr = malloc(nrows * sizeof(int *));
// Allocate each row of the triangular array
for (int i = 0; i < nrows; i++)
{
int rowlen = i+1;
// Allocate a row of ints for the array
arr[i] = malloc(rowlen * sizeof(int));
// Fill the row with '1' values
for (int j = 0; j < rowlen; j++)
arr[i][j] = 1;
}
// Return the allocated array
return arr;
}
// Test driver
void test(int n)
{
int ** arr;
arr = make_triangle_array(n);
...
free_triangle_array(arr, n);
}
This approach has the advantage of being able to allocate any size for each row. It also has the advantage of being able to use the syntax arr[x][y]
to access a given element within the array.
(This is very similar to the way languages like Java and C# allocate multi-dimensional arrays using references.)
Note that you when you are done using the array, you have to deallocate it in two steps; first you have to deallocate each row of the array, and then you have to deallocate the array (of pointers) itself.
// Deallocate a 2-D array
void free_triangle_array(int **arr, int nrows)
{
// Free each allocated row
for (int i = 0; i < nrows; i++)
{
if (arr[i] != NULL)
free(arr[i]);
arr[i] = NULL;
}
// Free the pointer array
free(arr);
}