I compile the code below with gcc using -Wall -Werror
and it compiles cleanly, runs as expected; however, I'm just curious if it is OK, in ANSI and/or ISO C context, to pass a (double ***)
pointer via (void **)
.
The ISO/IEC 9899:2017, section 6.6 - 9 says:
"The array-subscript
[]
and member-access.
and->
operators, the address&
and indirection*
unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators."
In connection to this recommendation, the function allocateMatrix
is, in fact, supposed to just allocate memory and return the corresponding address; so, please disregard the inner loop that assign values, it's there for test purposes only.
void allocateMatrix(int n, void **a) {
int i = 0, j = 0;
double **pTmp = calloc(n, sizeof(double *));
for (i = 0; i < n; i++) {
pTmp[i] = malloc(n * sizeof(double));
// following loop is inserted to make sure code runs as expected
// this does not exists in real code
for (j = 0; j < n; j++) {
pTmp[i][j] = (double)(i + 1) + (double)(j + 1) / 10.0f;
}
}
*a = pTmp;
return;
}
int main(int argc, char const *argv[]) {
int i = 0, j = 0;
int n = 5;
double **a = NULL;
// "a" is a (double **) pointer; so, "&a" is now a (double ***) pointer
allocateMatrix(n, (void **)&a);
// testing...
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%6.2lf", a[i][j]);
}
printf("\n");
}
return 0;
}
The C standard allows for conversion to and from void *
, however that lattitute does not exist for void **
.
Change the function argument to void *
and cast it appropriately and it will work.
void allocateMatrix(int n, void *a) {
...
*(double ***)a = pTmp;
}
And change remove the cast from the function call:
allocateMatrix(n, &a);