A void pointer (void*) is a special type of pointer that can store the address of any data type. Since it is not associated with a specific type, it is also known as a generic pointer.
- Can point to objects of any data type.
- Must be typecast before dereferencing.
#include <iostream>
using namespace std;
int main()
{
int a = 10;
// void pointer holds address of int 'a'
void* myptr = &a;
// printing the value of a and adress of a stored in
// myptr
cout << "The value of a is: " << a << endl;
cout << "The Adress of a is " << myptr << endl;
}
Output
The value of a is: 10 The Adress of a is 0x7ffd9ac02a64
Explanation: The void pointer stores the address of an integer variable. Since it does not know the data type of the object it points to, only the address can be printed directly.
Syntax
void* ptr_name;
Here,
- void indicates that the pointer is not associated with any specific data type.
- ptr_name is the name of the pointer.
Dereferencing a Void Pointer
A void pointer cannot be dereferenced directly because the compiler does not know the type and size of the object it points to. Therefore, it must first be converted to the appropriate pointer type.
#include <iostream>
using namespace std;
int main()
{
int x = 50;
void* ptr = &x;
cout << *(static_cast<int*>(ptr));
return 0;
}
Output
50
Explanation: The void pointer is first converted to an int* using static_cast, after which it can be safely dereferenced.
Using Void Pointer with Different Data Types
One of the biggest advantages of a void pointer is that the same pointer can point to different types of variables.
#include <iostream>
using namespace std;
int main()
{
int n = 10;
float f = 25.5f;
char c = '$';
void* ptr;
ptr = &n;
cout << *(static_cast<int*>(ptr)) << endl;
ptr = &f;
cout << *(static_cast<float*>(ptr)) << endl;
ptr = &c;
cout << *(static_cast<char*>(ptr)) << endl;
return 0;
}
Output
10 25.5 $
Explanation: The same void pointer stores the addresses of variables of different types. Before accessing each value, it is typecast to the corresponding pointer type.
Application of Void Pointer
A void pointer is commonly used when the exact data type is not known beforehand or when the same piece of code needs to work with multiple data types.
Generic Programming
One of the most common uses of a void pointer is writing generic code. Unlike typed pointers, which can point to only one data type, a void pointer can store addresses of different data types, making code more reusable.
Example: Using an int Pointer
#include <iostream>
using namespace std;
int main()
{
int* ptr;
float f = 90.6;
ptr = &f; // error
cout << "The value of *ptr is : " << *ptr << endl;
return 0;
}
Output
error: cannot convert ‘float*’ to ‘int*’ in assignmentExplanation: An int* pointer can only store the address of an integer variable. Assigning it the address of a float results in a compilation error.
A void pointer removes this restriction.
Example: Using a Void Pointer
#include <iostream>
using namespace std;
int main()
{
int n = 10;
float f = 25.25;
char c = '$';
void* ptr;
ptr = &n;
cout << "Address of n: " << ptr << endl;
ptr = &f;
cout << "Address of f: " << ptr << endl;
ptr = &c;
cout << "Address of c: " << ptr << endl;
return 0;
}
Output
Address of n: 0x7fffffffe9c4 Address of f: 0x7fffffffe9c0 Address of c: 0x7fffffffe9bf
Explanation: The same void pointer is reused to store the addresses of variables of different data types. Since a void pointer has no associated type, it can point to any object. However, to access the stored value, it must first be typecast to the correct pointer type.
Dynamic Memory Allocation
Void pointers are useful when dynamically allocated memory needs to be handled in a generic way. After allocating memory, the pointer can be converted to the required type before accessing the allocated object.
#include <iostream>
using namespace std;
int main()
{
// Allocate memory
void* voidPtr = new int;
// Convert to int*
int* intPtr = static_cast<int*>(voidPtr);
*intPtr = 42;
cout << "Value from allocated memory: "
<< *intPtr << endl;
delete intPtr;
return 0;
}
Output
Value from allocated memory: 42
Explanation: Memory is allocated and its address is stored in a void pointer. After casting it to int*, the allocated memory can be accessed and modified normally.
Note: In modern C++, new already returns a typed pointer, so storing it in a void pointer is generally unnecessary. Void pointers are more commonly used with C libraries (such as malloc()) or generic APIs.
Callback Functions
Void pointers are widely used in callback functions and generic APIs where the type of data passed to the callback is determined at runtime. A single callback function can process different data types by casting the void pointer appropriately.
#include <iostream>
using namespace std;
// Callback function
void CallbackFunction(void* data, char dataType)
{
switch (dataType) {
case 'i':
cout << "Callback for integer: "
<< *(int*)data << endl;
break;
case 'd':
cout << "Callback for double: "
<< *(double*)data << endl;
break;
default:
cout << "Unsupported data type!"
<< endl;
}
}
// Function that accepts a callback
void PerformOperation(void* data,
char dataType,
void (*callback)(void*, char))
{
callback(data, dataType);
}
int main()
{
int intValue = 7;
double doubleValue = 8.12;
PerformOperation(&intValue, 'i',
CallbackFunction);
PerformOperation(&doubleValue, 'd',
CallbackFunction);
return 0;
}
Output
Callback for integer: 7 Callback for double: 8.12
Explanation: The callback function receives a void pointer along with information about the actual data type. It casts the pointer to the appropriate type before accessing the value, allowing the same callback to work with multiple data types.
Advantages of Void Pointer in C++
Void pointers provide flexibility when writing generic code and working with APIs that handle multiple data types.
- Can store the address of variables of any data type.
- Helps write reusable and generic functions.
- Useful in callback functions and generic libraries.
- Simplifies interaction with C libraries and low-level APIs.
- Can improve portability when working with platform-independent interfaces.
Limitations of Void Pointer in C++
Although flexible, void pointers should be used carefully because they sacrifice type safety.
- Cannot be dereferenced without typecasting.
- The compiler cannot perform type checking.
- Incorrect typecasting can lead to undefined behavior.
- Makes code harder to read and maintain compared to typed pointers.