Void Pointers
Every pointer type you have seen so far — int *, char *, struct Point * — points to a specific, known kind of data. A void * is different: it is a generic pointer that can hold the address of any data type, without saying what that data actually is. It is C's way of writing code that works with "some memory, type unspecified."
int i = 10; double d = 3.14; char c = 'A'; void *anything; anything = &i; // OK, void* can point to anything anything = &d; // still OK anything = &c; // still OK
You cannot dereference a void pointer directly
#include <stdio.h>
int main(void) {
int i = 10;
void *anything = &i;
// printf("%d\n", *anything); // ERROR: cannot dereference void*
int *as_int = (int *)anything; // cast first
printf("%d\n", *as_int); // OK
return 0;
}10
Where void pointers show up in the standard library
void * is the backbone of several familiar standard library functions, precisely because it lets them work with any data type without being rewritten for each one:
void *malloc(size_t size)— returns a generic block of memory; you cast it to whatever pointer type you need.void *memcpy(void *dest, const void *src, size_t n)— copies raw bytes between any two buffers, regardless of type.void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))— sorts an array of any element type by calling back into a comparison function you supply.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
// malloc returns void*; it works for any type.
int *nums = malloc(5 * sizeof(int));
double *vals = malloc(5 * sizeof(double));
// memcpy takes void* source/destination; it doesn't care what type
// the buffers actually are.
int src[3] = {1, 2, 3};
int dst[3];
memcpy(dst, src, sizeof(src));
printf("dst = {%d, %d, %d}\n", dst[0], dst[1], dst[2]);
free(nums);
free(vals);
return 0;
}dst = {1, 2, 3}A crude form of generic programming
C has no templates or generics built into the language. void * combined with an explicit size parameter (so the function knows how many bytes each element occupies, even though it does not know their type) is how the standard library fakes it: qsort can sort an array of int, struct Employee, or anything else, because it never actually looks inside the elements itself — it just moves raw bytes around and calls your comparison function to decide their order.