student@ubuntu:~$
Topic Week 7 2 min overview

void *

The type-erased pointer, C's answer to generic programming

In a nutshell

void * is a pointer with no type attached. You cannot dereference it directly, but you can cast it to any other pointer type and then read or write through that cast. Library functions that must work on “any data” use void * in their signatures: memcpy, memset, qsort, malloc. It is C’s minimal version of Java’s generics.

Why it matters

Every generic container pattern in C (stacks, queues, hash tables that can hold any element type) uses void * at its interface. Lab 9 asks you to write a generic container, which is impossible without understanding the void * idiom. Also, malloc returns void * (you cast it to whatever you wanted), so every dynamic allocation you have been doing has been using void * under the hood.

Key takeaways

  • void * has no size information. You cannot do void *p; p++; because the compiler does not know what to advance by.
  • Cast to use. int *ip = (int *)vp; *ip = 42; is the canonical pattern.
  • sizeof is how generic code moves through arrays. Pass an element size as a parameter: void copy(void *dst, const void *src, size_t n, size_t element_size);.
  • memcpy and memset are the two primitives that operate on raw bytes through void *. They are the building blocks of any generic container.
  • malloc returns void *. The common idiom int *p = malloc(n * sizeof(int)); relies on an implicit cast.

Lessons in this topic

Lesson What it covers
Void Pointers Declaring void *, the cast-to-use idiom, passing element size, memcpy/memset

Practice and deep dives

Practice this topic: browse the practice gallery.

What comes next

Function Pointers — pointers to code rather than data. Together with void *, they make generic algorithms possible: qsort takes a void * array plus a comparator function pointer.