Generic Pointer To Pointer

From C

Jump to: navigation, search

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

.

Personal tools