I have two questions regarding this code.
-
What does the
double*** pdataandint*** pmaskmean? A pointer to a pointer to a pointer?
Why or when is this necessary? -
intanddoubleare different types, but aredouble*andint*also different. Can we operate on them without a cast?
Here’s the code I’m puzzled about:
static int makedatamask(int nrows, int ncols, double*** pdata, int*** pmask)
{ int i;
double** data;
int** mask;
data = malloc(nrows*sizeof(double*));
if(!data) return 0;
mask = malloc(nrows*sizeof(int*));
if(!mask)
{ free(data);
return 0;
}
for (i = 0; i < nrows; i++)
{ data[i] = malloc(ncols*sizeof(double));
if(!data[i]) break;
mask[i] = malloc(ncols*sizeof(int));
if(!mask[i])
{ free(data[i]);
break;
}
}
if (i==nrows) /* break not encountered */
{ *pdata = data;
*pmask = mask;
return 1;
}
*pdata = NULL;
*pmask = NULL;
nrows = i;
for (i = 0; i < nrows; i++)
{ free(data[i]);
free(mask[i]);
}
free(data);
free(mask);
return 0;
}
Yes – the types are triple pointers or pointers to pointers to pointers. Occasionally they are necessary, but be very scared. In this case, you are allocating two similarly sized 2D arrays, and you have to return the two values by reference, so the triple pointers are necessary, at least while you keep the current function design.
Yes – a
double *and anint *are different types; they point to different types. You can do appropriate operations on them without a cast. However, if you are thinking that you can combine the two parallel operations into one, you are probably mistaken.Your error recovery might be simpler if you created some sub-functions:
Your main allocation function would then simply call these two sequentially. If the second failed, the main allocation function would call the cleanup for the first allocated array. The cleanup code probably needs the relevant size, so you’d probably have:
These functions might even be visible outside the source (not
static).You might also consider using a structure to describe the arrays (rows and columns), and the pointers to the arrays. This would allow you to avoid the explicit triple-pointer notation too.
Etc.