It\'s the special property that void* can also be assigned a pointer to a pointer and cast back and the original value is received.
I read this line
One points at a black hole.
The other points at the thing pointing at the black hole.
They're not really the same thing, but pointers can be converted to void *
. You can convert int *
to a void *
because, well, it's a pointer. void **
is still a pointer (it just points to a pointer), and since it's a pointer, you can convert it to a void *
. That make any sense?
That said, I don't think I've ever had a use for a void **
, but if you needed an array of void *
s, then the type would be void **
. (In C) void *
is often used to hold a pointer to some user data - but you won't know ahead of time what type that data will be. If you had an array of those, then void **
.
Since you also have this tagged as C++: The previous case doesn't really apply: you could use a std::vector<void *>
. Really, void *
might be questionable - an abstract base might fit your purposes better. void *
is useful mostly in C.
A void** is a pointer to a void*. A void* can be converted back and forth to any pointer type (including void**). So you can do:
char* -> void*
void* -> void**
void** -> void*
void* -> char*
You can not do:
char* -> void**
void** -> char*
so they are not the same.
A void *
can hold any pointer. Since there are no actual void
objects, a void *
is always a pointer to some other type.
A void **
is a pointer to a pointer to void, or the address of a void *
, i.e., the address of a pointer to void. This is an actual type and doesn't have any magic properties.
But since a void *
can hold any pointer, it can also hold, for example, a void **
.
void **f(int x) {
static void *y;
static int *iy;
y = &x;
iy = &x;
// return &iy; // not ok
return &y; // ok
}
if you want to store some pointer or anything you will probably use void*.
However if you want to write a function which can be able to initialize this magic pointer, then you need pass this argument to this function as void**
void fun1();
int fun2(int);
double fun3(long);
bool fun4(int, long, double);
int rand(void** pp)
{
switch(time()%4)
{
case 0: *pp = fun1; return 0;
case 1: *pp = fun2; return 1;
case 2: *pp = fun3; return 2;
case 3: *pp = fun4; return 3;
}
}
int main()
{
void* pointer;
int funId;
funId = rand(&pointer);
setCallback(pointer, funId);
}
void* is a pointer (or a pointer to the beginning of a unknown type array). void* is a pointer to the address of a pointer (or a pointer to the beginning of a 2D array).
Also, if you are writing in C (and not in C++), then there is no by-reference parameter, only by value or by pointer.
E.g.
// By value C and C++
void MyFunction(int a)
{
}
// By pointer C and C++
void MyFunction(int* a)
{
}
// By reference C++ only
void MyFunction(int& a)
{
}
If you want a function that modifies the address of a pointer (e.g. void* ptr;)
and enables the calling code to by affected by the change,
then you need to pass a pointer by reference pass ptr to (void*&) and use ptr inside the function
or pass a pointer to a pointer (void**) and pass &ptr and use *ptr inside the function.
One major difference is that the rule you quote in bold does not apply to void**.