14

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 somewhere. Does it means void* and void** are same? What is the difference?

Edit

void* can hold any pointer. Then what's void** needed for?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mohit Jain
  • 43,139
  • 57
  • 169
  • 274
  • You need void** when you need to dereference it and find out what the void* it's pointing to is, or even change that void* to something else. You can't dereference void*, or shouldn't without heavy-duty safety goggles on. – Owen S. Jun 12 '10 at 02:55
  • Well, if you want to think about it that way, what are any pointer types other than `void*` needed for? – JohnMcG Sep 12 '10 at 12:34

6 Answers6

56

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.

Thanatos
  • 42,585
  • 14
  • 91
  • 146
  • 2
    I've used void ** as a parameter to a function that called a function pointer passed to it. In this particular case, the baton was mutable. – Joshua Jun 11 '10 at 23:11
  • An array of `void*`s is actually `void*[n]`. – fredoverflow Aug 13 '12 at 08:23
  • @FredOverflow: Strictly speaking, yes. When I wrote the post, I was thinking more along the lines of a dynamically allocated array, or an array who's size is not known. – Thanatos Sep 20 '12 at 19:59
7

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.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
3

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
}
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • Keep in mind that the opposite, a void** can hold a void*, is NOT guaranteed. – Edward Strange Jun 11 '10 at 23:06
  • Good point, I was trying to say that, actually. That's why that one return line, which attempts to put a `void *` into a `void **`, is commented out with the *not ok* note. – DigitalRoss Jun 11 '10 at 23:27
2

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);
}
noisy
  • 6,495
  • 10
  • 50
  • 92
  • Right idea, but you're confusing function pointers with data pointers--this is non-standard. Make that four different struct types instead and you're right on. – Drew Hall Sep 12 '10 at 09:14
1

One major difference is that the rule you quote in bold does not apply to void**.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
0

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.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
Danny Varod
  • 17,324
  • 5
  • 69
  • 111