What is void* and to what variables/objects it can point to
void*
is such a pointer, that any pointer can be implicitly converted to void*
.
For example;
int* p = new int;
void* pv = p; //OK;
p = pv; //Error, the opposite conversion must be explicit in C++ (in C this is OK too)
Also note that pointers to const cannot be converted to void*
without a const_cast
E.g.
const int * pc = new const int(4);
void * pv = pc; //Error
const void* pcv = pc; //OK
Hth.
What does void* mean and how to use it?
A pointer to void
is a "generic" pointer type. A void *
can be converted to any other pointer type without an explicit cast. You cannot dereference a void *
or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.
void *
is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort
:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base
is the address of an array, nmemb
is the number of elements in the array, size
is the size of each element, and compar
is a pointer to a function that compares two elements of the array. It gets called like so:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
The array expressions iArr
, dArr
, and lArr
are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int
/double
/long
" to "pointer to void
".
The comparison functions would look something like:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
By accepting void *
, qsort
can work with arrays of any type.
The disadvantage of using void *
is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt
is expecting its arguments to be pointing to int
s, but is actually working with double
s. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.
void pointer vs object in function parameters
A pointer refers to a variable.
An instance of object
refers to a value.
This is a very key difference. Using a pointer you can mutate another variable (usually one that's not currently in scope). Using an object
instance you can only ever mutate a value, possibly one that another variable also reference, but that's still a key difference.
Because the pointer refers to a variable, mutations to the referred to variable variable will be observable through the pointer. The pointer is also capable of mutating that variable. An object
instance on the other hand is not tied to another variable. Even if the object it refers to is referred to by another variable, changes in that other variable won't be observable through the object
instance, and it also has no way of mutating the other variable.
There's also the fact that for an object
to reference a value type that value type needs to be boxed. This can have performance implications in that the values end up being copied, but also significant semantic differences. Mutations of the source variable won't be visible to the object
reference, while they would be had you used a void
pointer.
Why use a void pointer for dereferencing variables of datatypes?
A void
pointer is a generic pointer which can hold the address of any type and can be typecast to any type.
In the first case, the program successfully compiled and ran without any warning or error, because using a void
pointer to convert from one pointer type to another and then storing or casting it to the final type is safe without losing data.
But in the second case the GCC compiler generated a warning
prog.c: In function 'main':
prog.c:5:9: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
int *ip=&a;
^
clang compiler:
warning: incompatible pointer types initializing 'int *' with an expression of type 'float *' [-Wincompatible-pointer-types]
int *ip=&a;
^ ~~
The C11 Standard, 6.3.2.3, paragraph 7:
A pointer to an object or incomplete type may be converted to a
pointer to a different object or incomplete type. If the resulting
pointer is not correctly aligned for the referenced type, the behavior
is undefined.
Related Topics
Overload Resolution and Arrays: Which Function Should Be Called
How to Build a Full Path String (Safely) from Separate Strings
The Std::Transform-Like Function That Returns Transformed Container
Is There a Reason Why Not to Use Link-Time Optimization (Lto)
Convert a Number to a String with Specified Length in C++
Eigen How to Concatenate Matrix Along a Specific Dimension
C++ Crashes in a 'For' Loop with a Negative Expression
Concatenate Compile-Time Strings in a Template at Compile Time
Clean Up Your #Include Statements
C++ Check If Statement Can Be Evaluated Constexpr
Does Std::Array<> Guarantee Allocation on the Stack Only
Opening a Window That Has No Title Bar with Win32
Vector: Initialization or Reserve
How to Determine the Correct Size of a Qtablewidget
Are Mutex Lock Functions Sufficient Without Volatile
Cross Platform Sleep Function for C++
Lambdas Require Capturing 'This' to Call Static Member Function