How do I allocate and have access to this pointer in C:
float **x;
such that I can work with it like an array, e.g. x[0][0]?
This is a FAQ.
6.16: How can I dynamically allocate a multidimensional array?
A: The traditional solution is to allocate an array of pointers,
and then initialize each pointer to a dynamically-allocated
"row." Here is a two-dimensional example:
#include <stdlib.h>
int **array1 = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
array1
= malloc(ncolumns * sizeof(int));
(In real code, of course, all of malloc's return values would
be checked.)
You can keep the array's contents contiguous, at the cost of
making later reallocation of individual rows more difficult,
with a bit of explicit pointer arithmetic:
int **array2 = malloc(nrows * sizeof(int *));
array2[0] = malloc(nrows * ncolumns * sizeof(int));
for(i = 1; i < nrows; i++)
array2 = array2[0] + i * ncolumns;
In either case, the elements of the dynamic array can be
accessed with normal-looking array subscripts: arrayx[j]
(for 0 <= i < nrows and 0 <= j < ncolumns).
If the double indirection implied by the above schemes is for
some reason unacceptable, you can simulate a two-dimensional
array with a single, dynamically-allocated one-dimensional
array:
int *array3 = malloc(nrows * ncolumns * sizeof(int));
However, you must now perform subscript calculations manually,
accessing the i,jth element with array3[i * ncolumns + j]. (A
macro could hide the explicit calculation, but invoking it would
require parentheses and commas which wouldn't look exactly like
multidimensional array syntax, and the macro would need access
to at least one of the dimensions, as well. See also question
6.19.)
Yet another option is to use pointers to arrays:
int (*array4)[NCOLUMNS] = malloc(nrows * sizeof(*array4));
but the syntax starts getting horrific and at most one dimension
may be specified at run time.
With all of these techniques, you may of course need to remember
to free the arrays (which may take several steps; see question
7.23) when they are no longer needed, and you cannot necessarily
intermix dynamically-allocated arrays with conventional,
statically-allocated ones (see question 6.20, and also question
6.18).
Finally, in C9X you can use a variable-length array.
All of these techniques can also be extended to three or more
dimensions.
References: C9X Sec. 6.5.5.2.