void * is a pointer to something of unknown type. Any object pointer converts to and from it implicitly — it is how C writes generic code (malloc, memcpy, qsort).
#include <stdio.h>
void print_value(const void *p, char type) {
switch (type) {
case 'i': printf("int %d\n", *(const int *)p); break;
case 'd': printf("double %.2f\n", *(const double *)p); break;
case 's': printf("string %s\n", (const char *)p); break;
}
}
int main(void) {
int i = 7;
double d = 2.5;
print_value(&i, 'i');
print_value(&d, 'd');
print_value("text", 's');
return 0;
}int 7
double 2.50
string textRules
You cannot dereference a
void *— cast it to a concrete type first.No pointer arithmetic on
void *in standard C (GCC allows it as an extension, treating the size as 1).T *→void *→T *round-trips safely. Converting to the wrong type and dereferencing is undefined behaviour.In C,
malloc’svoid *result needs no cast:int *p = malloc(n * sizeof *p);. (C++ requires one.)Function pointers are not guaranteed to convert to
void *(POSIX allows it fordlsym).
A generic swap
#include <stdio.h>
#include <string.h>
void swap_any(void *a, void *b, size_t size) {
unsigned char tmp[64]; /* enough for this demo */
if (size > sizeof tmp) return;
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
}
int main(void) {
int x = 1, y = 2;
double p = 1.5, q = 9.75;
swap_any(&x, &y, sizeof x);
swap_any(&p, &q, sizeof p);
printf("%d %d %.2f %.2f\n", x, y, p, q);
return 0;
}2 1 9.75 1.50A generic linear search
#include <stdio.h>
#include <string.h>
/* returns the index of the first element equal to key, or -1 */
long find(const void *base, size_t n, size_t size, const void *key,
int (*eq)(const void *, const void *)) {
const unsigned char *p = base; /* byte pointer for arithmetic */
for (size_t i = 0; i < n; i++)
if (eq(p + i * size, key)) return (long)i;
return -1;
}
int eq_int(const void *a, const void *b) { return *(const int *)a == *(const int *)b; }
int eq_str(const void *a, const void *b) {
return strcmp(*(const char *const *)a, *(const char *const *)b) == 0;
}
int main(void) {
int nums[] = {3, 1, 4, 1, 5};
int k = 4;
const char *names[] = {"ann", "bob", "cy"};
const char *who = "cy";
printf("%ld %ld\n", find(nums, 5, sizeof nums[0], &k, eq_int),
find(names, 3, sizeof names[0], &who, eq_str));
return 0;
}2 2Why can't a void pointer be dereferenced?
Why does qsort's comparator take const void *?