tags:

views:

280

answers:

6

I would look this up, but honestly I wouldn't know where to start because I don't know what it is called. I've seen variables passed to functions like this:

myFunction((void**)&variable);

Which confuses the heck out of me cause all of those look familiar to me; I've just never seen them put together like that before.

What does it mean? I am a newb so the less jargon, the better, thanks!

+1  A: 

That casts &variable to a void** (that is, a pointer to a pointer to void).

For example, if you have something along the lines of

void myFunction(void** arg);

int* variable;

This passes the address of variable (that's what the unary-& does, it takes the address) to myFunction().

James McNellis
+4  A: 

It's a cast to a pointer to a void pointer.

You see this quite often with functions like CoCreateInstance() on Windows systems.

ISomeInterface* ifaceptr = 0;
HRESULT hr = ::CoCreateInstance(CLSID_SomeImplementation, NULL, CLSCTX_ALL,
    IID_ISomeInterface, (void**)&ifaceptr);
if(SUCCEEDED(hr))
{
    ifaceptr->DoSomething();
}

The cast converts the pointer to an ISomeInterface pointer into a pointer to a void pointer so that CoCreateInstance() can set ifaceptr to a valid value.

Since it is a pointer to a void pointer, the function can output pointers of any type, depending on the interface ID (such as IID_ISomeInterface).

In silico
That makes sense. But I never heard of handling an variable of a unknown datatype. How would CoCreateInstance handle ifaceptr, if it does not know what type it is. secondly, is the void size arbitrary to the size of the original datatype.
numerical25
CoCreateInstance always creates a pointer to a COM Object, and returns it through the `void**` parameter. You tell it what type you want, in the form of the `IID_ISomeInterface` parameter, and you're responsible for using typecasts correctly to turn the `void**` into something you can use.
Ken Bloom
`CoCreateInstance()` "knows" what type the output pointer should be according to the interface ID (that's what `IID_ISomeInterface` is for in the example). Also, **all** pointers are the same size for a given architecture (e.g. all pointers on a 32-bit system are 4 bytes, while all pointers on a 64-bit system are 8 bytes). There's no such thing as a `void` type, but you can have `void` pointers. It basically means a pointer to any type.
In silico
I see what your saying. And I have seen variables where you can pass in a varible datatype FLAG. I never knew why, but I think I know why now. I am also guessing you can never start a variable of type void either. For example void* myVar. You have to first specify a datatype, then cast it to a void type when calling a function that request it. Correct me if I am wrong on that.
numerical25
Oh no, you can declare a variable of a `void*` type, like `void* myVar;`. You just can't have a variable of a `void` type, like `void myVar;`. You can't do much with a `void*` pointer, which is why we often cast it to something else.
In silico
Concerning `void*` casting, you can always cast to and from a `void` pointer. Whether the cast is safe or not is a different question. For example, casting a `Foo*` to a `void*` then back to a `Foo*` is always safe, but casting a `Bar*` to a `void*` then back to a `Foo*` is most definitely not safe (assuming `Foo` and `Bar` are unrelated). That's why we tell `CoCreateInstance()` what type the `void` pointer actually is via an identifier.
In silico
(Actually, function pointers may not all be the same size, due to the way compilers typically implement them)
In silico
+2  A: 

It's a pointer to a pointer to a variable with an unspecified type. All pointers are the same size, so void* just means "a pointer to something but I have no idea what it is". A void** could also be a 2D array of unspecified type.

Brendan Long
+4  A: 

void* is a "pointer to anything". void ** is another level of indirection - "pointer to pointer to anything". Basically, you pass that in when you want to allow the function to return a pointer of any type.

&variable takes the address of variable. variable should already be some kind of a pointer for that to work, but it's probably not void * - it might be, say int *, so taking its address would result in a int **. If the function takes void ** then you need to cast to that type.

(Of course, it needs to actually return an object of the right type, otherwise calling code will fail down the track when it tries to use it the wrong way.)

Evgeny
ok so the calling function has to request the type void as a arguement in order for me to cast my object as void. But I guess the follow up question is what does the datatype void have to offer that will be beneficial to the function ? If void represents an unknown datatype, then this means that the properties and values are unknown as well.
numerical25
It allows you to get around the type checking that would normally go on; you could (for example) have a function that take a pointer to a function, and an argument to call it with, then returns the result. If you had to specify the type (e.g. char*, int*, etc) you would have to have a function for each argument type; using void* you can use the data without caring what the actual types are.
El Yobo
A: 

The variable is a pointer to something of undefined (void) type. The & operator returns the address of that variable, so you now have a pointer to a pointer of something. The pointer is therefore passed into the function by reference. The function might have a side effect which changes the memory referenced by that pointer. In other words, calling this function might change the something that the original pointer is referencing.

lach
+1  A: 

Take it apart piece by piece...

myFunction takes a pointer to a pointer of type void (which pretty much means it could point to anything). It might be declared something like this:

myFunction(void **something);

Anything you pass in has to have that type. So you take the address of a pointer, and cast it with (void**) to make it be a void pointer. (Basically stripping it of any idea about what it points to - which the compiler might whine about otherwise.)

This means that &variable is the address (& does this) of a pointer - so variable is a pointer. To what? Who knows!

Here is a more complete snippet, to give an idea of how this fits together:

#include <stdio.h>

int myInteger = 1;
int myOtherInt = 2;
int *myPointer = &myInteger;

myFunction(void **something){
    *something = &myOtherInt;
}

main(){
    printf("Address:%p Value:%d\n", myPointer, *myPointer);
    myFunction((void**)&myPointer);
    printf("Address:%p Value:%d\n", myPointer, *myPointer);
}

If you compile and run this, it should give this sort of output:

Address:0x601020 Value:1
Address:0x601024 Value:2

You can see that myFunction changed the value of myPointer - which it could only do because it was passed the address of the pointer.

Kim Reece
Oooo, ok. So correct me if I am wrong. A void pointer is only meant to hold any type of datatype. once a specific datatype is casted to the void pointer, then the void pointer becomes of that datatype. and Of course, I can not pass a void pointer into a function unless the function request for it.
numerical25
A pointer is just a value - an address in memory. Its type is an indication to the compiler of what sort of thing it points to. A void pointer is like telling the compiler that you're not going to tell it what type the pointer might point to.When passing parameters, you always have to match the type that the function is declared to accept. So if the function wants a void** and you have an int**, you have to cast it to be what the function expects.
Kim Reece