Pointers to the Void: Advanced C Tricks

In C, the void* pointer is both the most powerful and the most dangerous tool in a programmer's arsenal. It represents raw, untyped memory — a gateway to generic programming in a language that has no generics.

The Nature of void*

A void* can hold the address of any data type. It is the lingua franca of C APIs, used in qsort(), bsearch(), pthread_create(), and countless other standard library functions.

void swap(void *a, void *b, size_t size) {
    char temp[size];
    memcpy(temp, a, size);
    memcpy(a, b, size);
    memcpy(b, temp, size);
}

Function Pointers: Code as Data

Function pointers allow you to store and pass around references to executable code. Combined with void* for data, this pattern enables polymorphism in C.

typedef int (*Comparator)(const void*, const void*);

int compare_int(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

// Usage with qsort
qsort(array, n, sizeof(int), compare_int);

Building a Generic Container

With void* and function pointers, you can build type-erased containers that rival C++ templates in functionality (though not in type safety).

typedef struct {
    void **items;
    size_t count;
    size_t capacity;
    size_t item_size;
    void (*destructor)(void*);
} GenericArray;

The Dangers of the Void

With great power comes great responsibility. Unsafe casts through void* bypass the type system entirely. A wrong cast is silent at compile time but catastrophic at runtime. Always document your void* contracts explicitly.

The void is not empty — it is full of potential. Navigate it carefully.