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; }
.