Your code may work on some platforms, but it is not portable. The reason is that C doesn't have a generic pointer to pointer type. In the case of void *
the standard explicitly permits conversions between it and other pointer to complete/incomplete types, but this is not the case with void **
. What this means is that in your code, the compiler has no way of knowing if the value of *vp
was converted from any type other than void *
, and therefore can not perform any conversions except the one you explicitly cast yourself.
Consider this code:
void dont_do_this(struct a_t **a, struct b_t **b)
{
void **x = (void **) a;
*x = *b;
}
The compiler will not complain about the implicit cast from b_t *
to void *
in the *x = *b
line, even though that line is trying to put a pointer to a b_t
in a place where only pointers to a_t
should be put. The mistake is in fact in the previous line, which is converting "a pointer to a place where pointers to a_t
can be put" to "a pointer to a place where pointers to anything can be put". This is the reason there is no implicit cast possible. For an analogous example with pointers to arithmetic types, see the C FAQ.
Your cast, then, even though it shuts the compiler warning up, is dangerous because not all pointer types may have the same internal representation/size (e.g. void **
and int *
). To make your code work in all cases, you have to use an intermediate void *
:
int *array;
void *varray = array;
void **vp = &varray;
*vp = malloc(sizeof(int) * 10);