A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
void* is a pointer to an unspecified type. It can hold the address of any object. You cannot dereference it directly because the compiler does not know how many bytes to read or how to interpret them. You must cast it to a concrete pointer type first. This is how C achieves genericity without templates or generics. malloc returns void*. memcpy takes void*. qsort's comparator takes void*. The entire standard library's type-agnostic interface is built on void*.
#include <stdio.h>int main(void) {int x = 42;double pi = 3.14159;char ch = 'Z';void *generic;generic = &x;printf("As int: %d\n", *(int *)generic);generic = πprintf("As double: %.5f\n", *(double *)generic);generic = &ch;printf("As char: %c\n", *(char *)generic);return 0;}
The same variable, generic, holds addresses of three different types. The cast at the dereference site tells the compiler how to interpret the bytes. Get the cast wrong and you read the wrong number of bytes or interpret the bit pattern incorrectly. There is no runtime type check. The compiler trusts your cast completely.
#include <stdio.h>#include <stdlib.h>int compare_ints(const void *a, const void *b) {int ia = *(const int *)a;int ib = *(const int *)b;return (ia > ib) - (ia < ib);}int main(void) {int arr[] = {38, 7, 92, 15, 4, 61};int n = sizeof(arr) / sizeof(arr[0]);qsort(arr, n, sizeof(int), compare_ints);printf("Sorted: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;}
qsort does not know what type it is sorting. It receives void* pointers to elements and a comparator that casts them to the correct type. The (ia > ib) - (ia < ib) idiom avoids subtraction overflow: it returns -1, 0, or 1 without computing ia - ib, which could overflow for extreme values.
You cannot perform pointer arithmetic on void* in standard C. The compiler does not know the element size. GCC allows it as an extension, treating void* like char*, but portable code must cast to a sized pointer type before doing arithmetic.
void* is C's mechanism for type-generic programming. It is unsafe by design. The safety comes from your discipline: cast correctly, document the expected type, and never assume. Next: dangling pointers, the zombie references that haunt C programs long after the data they pointed to is gone.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.