Generic Pointer To Pointer
From C
A pointer to pointer to void (void **) is not the same as a pointer to void. A pointer to void (void *) can be converted to and from pointers to object or incomplete types, where a pointer to pointer to void is not required to be convertible to other types of pointers to pointers. A pointer to void can be used for pointers to pointers, but there no generic pointer to pointer type.
The difference between a generic pointer (such as a pointer to void) and a generic pointer to pointer, is that we can't access the thing the generic pointer points to without its complete type, where a generic pointer to pointer would allow us to store pointers without the need of a specific type. The following code sample illustrates a memory allocator function, the only way we could have used the convention of passing our pointer to the function, and assign to it generically, is only if we had such a generic pointer to pointer.
#include <stdio.h>
#include <stdlib.h>
void my_malloc(int **pp, size_t size) {
*pp = malloc(size);
}
int main(void) {
int *p;
my_malloc(&p, sizeof *p);
return 0;
}
Since we don't have a generic pointer to pointer, our memory allocator function has to use the explicit pointer to pointer to int (int **) type as its parameter type, and this is the reason why memory allocators tend to use their return values with a pointer to void type for this purpose, then the assignment and the implicit pointer convernsion is being performed with the context of an explicit pointer type.
Non-standard approach
The non-standard approach makes the assumption that a pointer to pointer to void is a generic pointer to pointer. The following code sample makes assumptions about implementation-specific features, which lead to undefined behavior as far as the C standard is concerned.
#include <stdio.h>
#include <stdlib.h>
void my_malloc(void *p, size_t size) {
void **pp = p;
*pp = malloc(size);
}
int main(void) {
int *p;
my_malloc(&p, sizeof *p);
if (p == NULL)
return -1;
*p = 123;
free(p);
return 0;
}
.
