A void pointer in C is a special type of pointer that can store the address of any data type. Since it does not have an associated data type, it is often referred to as a generic pointer.
- A void pointer can hold the address of variables of any data type.
- Before accessing the value stored at a void pointer, it must be explicitly typecast to the appropriate pointer type.
Example: The following program demonstrates that a void pointer can store the address of different data types
#include <stdio.h>
int main()
{
int a = 10;
char b = 'x';
// Void pointer stores address of int
void* ptr = &a;
// Void pointer stores address of char
ptr = &b;
return 0;
}
Properties of Void Pointers
Void Pointers Cannot Be Dereferenced Directly
Since a void pointer has no associated data type, the compiler does not know how many bytes should be accessed during dereferencing.
Example: Invalid Dereferencing
#include <stdio.h>
int main()
{
int a = 10;
void* ptr = &a;
printf("%d", *ptr);
return 0;
}
Output
Compiler Error: 'void*' is not a pointer-to-object typeTo access the value stored at a void pointer, it must first be typecast to the correct pointer type.
Example: Dereferencing After Typecasting
#include <stdio.h>
int main()
{
int a = 10;
void* ptr = &a;
// The void pointer 'ptr' is cast to an integer pointer
// using '(int*)ptr' Then, the value is dereferenced
// with `*(int*)ptr` to get the value at that memory
// location
printf("%d", *(int*)ptr);
return 0;
}
Output
10
Explanation: The void pointer is first converted to an integer pointer using (int*)ptr, after which it can be safely dereferenced.
Pointer Arithmetic Is Not Allowed on Void Pointers
According to the C standard, pointer arithmetic cannot be performed directly on void pointers because the size of the pointed object is unknown. However, some compilers such as GCC allow pointer arithmetic on void pointers by treating the size of void as 1 byte.
#include <stdio.h>
int main()
{
// Declare and initialize an integer array 'a' with two
// elements
int a[2] = { 1, 2 };
// Declare a void pointer and assign the address of
// array 'a' to it
void* ptr = &a;
// Increment the pointer by the size of an integer
ptr = ptr + sizeof(int);
// The void pointer 'ptr' is cast to an integer
// pointer using '(int*)ptr' Then, the value is
// dereferenced with `*(int*)ptr` to get the value at
// that memory location
printf("%d", *(int*)ptr);
return 0;
}
Output
2
Note: This behavior is compiler-specific and may not work on all compilers. For portable code, convert the void pointer to a character pointer before performing pointer arithmetic.
Applications of Void Pointers in C
Void pointers are widely used in C programming because they provide generic programming capabilities.
- Functions such as malloc(), calloc(), and realloc() return a void*, allowing memory allocation for any data type.
int* arr = (int*) malloc(5 * sizeof(int));
- Void pointers enable functions to work with multiple data types. For example, the comparison function used by qsort() accepts void pointers.
- Many dynamic data structures such as linked lists, stacks, queues, and trees use void pointers to store elements of different types.
- Void pointers are commonly used for explicit typecasting between different pointer types.
- Many library functions use void pointers to provide flexible interfaces that work with arbitrary data.
Advantages of Void Pointers
Void pointers provide flexibility by allowing a single pointer type to work with multiple data types and generic programming constructs.
- Can store the address of variables of any data type.
- Useful for implementing generic functions and libraries.
- Widely used in dynamic memory allocation functions such as malloc() and calloc().
- Helps in implementing generic data structures like linked lists, trees, and queues.
Limitations of Void Pointers
Despite their flexibility, void pointers reduce type safety and require careful handling.
- Cannot be dereferenced directly without typecasting.
- Pointer arithmetic on void pointers is not allowed by the C standard.
- Incorrect typecasting can lead to undefined behavior.
- Provides less compile-time type checking compared to typed pointers.
Related article: C Programming Course Online with Data Structures