I'm rewriting a bunch of C99 VLAs for an open source project for support in Visual Studio. So I have a lot of statements like
void somefunc(double var[r]){...}
which I rewrite to
void somefunc(double *var) {
var = malloc(sizeof(double) * r);
...
free(var);
}
Which I am assuming to be the correct way to do this.
The problem is I am starting to see some more complicated VLA declarations which are leaving me stumped. For example:
double *(*var)[length1][length2][length3] = malloc(sizeof(double *[length4][length1][length2][length3]));
So to me this essentially looks like a 5 dimensional array.
This is clearly illegal in C89 because of the use of variables in the sizeof()
function.
My guess on how to rewrite this would be:
double *****var = malloc(sizeof(double ****) * length1);
for(int i = 0; i<length1; i++) {
var[i] = malloc(sizeof(double ***) * length2);
for(int j = 0; j<length2; j++) {
var[i][j] = malloc(sizeof(double **) * length3);
for(int k = 0; k<length3; k++) {
var[i][j][k] = malloc(sizeof(double *) * length4);
}
}
}
As messy as it is, this is my best guess on how to rewrite the above statement. Is this technically correct, and is there a better way I should be going about this?
Here's my attempt:
double***** var = malloc(sizeof *var * length4);
for (int i = 0; i < length4; ++i)
{
var[i] = malloc(sizeof *var[i] * length1);
for (int j = 0; j < length1; ++j)
{
var[i][j] = malloc(sizeof *var[i][j] * length2);
for (int k = 0; k < length2; ++k)
{
var[i][j][k] = malloc(sizeof *var[i][j][k] * length3);
for (int l = 0; l < length3; ++l)
{
var[i][j][k][l] = NULL;
// var[i][j][k][l] is a double* - you can allocate some room for a double here, or assign the address of an existing variable
}
}
}
}
Similar to yours, except that note how I used length4
in the first malloc
. If you look at your original declaration, var
is a pointer to a three dimensional array of double*
. As we can deduce from the malloc
call on the right, memory for length4
such arrays is allocated, so you can think of var
as an array of length4
three-dimensional arrays of double*
.
I still maintain that anyone who puts such stuff in production code ought to be shot on the spot (well, you, as a maintainer, are excused).
IIRC declaring variables inside for
s isn't valid C89, but you can move these above to the top of your scope.
Note that, as @immibis points out in the comments, your first conversion is most likely a mistake; double *var
is an argument to the function, which means it's passed by value, so any changes you make to it inside the function aren't visible outside, and on top of that, you malloc
some memory, do stuff with it, then free
it. Even if you were modifying a passed pointer - which would require the parameter type to be double**
- it still isn't necessary to pass a variable so you can use it locally exclusively. You most likely wanted to malloc
the memory outside of the function and pass a valid pointer (and hopefully the size) to it.