A void pointer is C’s “points at anything” type — it can hold the address of an int, a struct, or a buffer, but it deliberately forgets the type along the way. This question from our C Programming Quiz App tests the round trip: store an address in a void *, cast it back, dereference. Is that valid C, an error, or undefined behavior?
The Quiz Question
int x = 42;
void *vp = &x;
printf("%d", *(int *)vp);
What is printed by this code?
- 42
- Address of x
- Compile error
- Undefined behavior
The Correct Answer: 42
The assignment void *vp = &x needs no cast — in C, any object pointer converts to void * and back implicitly. The expression *(int *)vp first casts vp back to int *, then dereferences, reading the original 42. The standard guarantees this round trip: converting a pointer to void * and back to the original type yields a pointer that compares equal to the original (C11 §6.3.2.3). Verified on gcc 13.3 and Apple clang 21, clean under -Wall -Wextra:
$ gcc -Wall -Wextra voidp.c && ./a.out 42
Why Each Wrong Answer Is Wrong
Why not “Address of x”?
The star at the front is doing its job: (int *)vp is the address, but *(int *)vp dereferences it. To print the address you’d write printf("%p", vp) — no cast needed there, since %p expects void * exactly.
Why not “Compile error”?
The cast is precisely what keeps this legal. What actually fails to compile is dereferencing the void * directly — void is an incomplete type, so there’s no object size or type to read:
printf("%d", *vp); /* no cast: constraint violation */
$ gcc -Wall -Wextra bad.c bad.c:5:20: warning: dereferencing 'void *' pointer bad.c:5:20: error: invalid use of void expression $ clang bad.c bad.c:5:20: error: argument type 'void' is incomplete
So this option contains a real rule — it just applies to *vp, not to *(int *)vp.
Why not “Undefined behavior”?
Casting back to the original type is the defined, guaranteed direction. UB would enter if you cast to a different, incompatible type — say *(float *)vp — which violates strict aliasing and may also break alignment rules. Round-tripping through void * to the exact type you started with is the pattern the standard exists to support.
Why void * Exists: Generic Interfaces
The whole C memory API runs on this mechanism. malloc returns void * because it can’t know what you’ll store; the implicit conversion means no cast is needed in C:
int *arr = malloc(10 * sizeof *arr); /* void* → int* implicitly */
Likewise memcpy, qsort‘s comparison callbacks, and thread start routines (pthread_create) all traffic in void * so one function can serve every type. The discipline that keeps it safe is exactly what the quiz encodes: whoever takes the pointer out must cast it back to the type that went in. If that pointed-to memory has meanwhile been freed, you’re in use-after-free territory — the cast can’t save you from a dead target.
Frequently Asked Questions
Can you dereference a void pointer in C?
Not directly — *vp is a compile error because void is incomplete; the compiler has no idea how many bytes to read. Cast to the correct object type first: *(int *)vp.
Do I need to cast the result of malloc in C?
No. void * converts implicitly to any object pointer type in C, so int *p = malloc(n) is idiomatic. (C++ is different — there the cast is required, which is why you sometimes see it in C code written by C++ programmers.)
Is casting a void pointer to the wrong type undefined behavior?
Dereferencing through the wrong type is — it violates strict aliasing, and possibly alignment. The guarantee only covers casting back to the original pointer type (or a compatible one, or char * for byte access).
Related Reading
- Pointers in C – Complete Guide
- Use-After-Free in C
- Returning a Pointer to a Local Variable
- C Aptitude Questions and Answers
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #45 in the C Programming Quiz App — 155 questions with explanations covering operators, pointers, memory, and more.
Download on Google Play →