Sign in to follow this  
jagguy

void type?

Recommended Posts

jagguy    100
i am confused with this code. VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof(Vertices), (void**)&pVertices, 0 ) ) ) why woud you need to recast (void**)&pVertices why not just this as I don't see why the recasting is needed ()&pVertices

Share this post


Link to post
Share on other sites
Aardvajk    13207
Quote:
Original post by jagguy
i am confused with this code.

VOID* pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(Vertices), (void**)&pVertices, 0 ) ) )

why woud you need to recast
(void**)&pVertices

why not just this as I don't see why the recasting is needed
()&pVertices


The cast is from void* to void**, ie from a pointer-to-void to a pointer-to-pointer-to-void, hence the & taking the address of the pointer-to-void.

HTH Paul

Share this post


Link to post
Share on other sites
ronkfist    100
Well to be sure ud have to give us the definition of the Lock() function.

I don't see why casting to void* would be illegal, its a neutral pointer type.

If your compiler gives cast warnings it means you might be doing something you don't want to do, so that's why it's better to do an explicit cast.

Share this post


Link to post
Share on other sites
Aardvajk    13207
Quote:
Original post by ronkfist
Well to be sure ud have to give us the definition of the Lock() function.

I don't see why casting to void* would be illegal, its a neutral pointer type.

If your compiler gives cast warnings it means you might be doing something you don't want to do, so that's why it's better to do an explicit cast.


It is not casting to void*, it is casting to void**. This is a different type.

Share this post


Link to post
Share on other sites
ronkfist    100
Quote:
Original post by EasilyConfused
Quote:
Original post by ronkfist
Well to be sure ud have to give us the definition of the Lock() function.

I don't see why casting to void* would be illegal, its a neutral pointer type.

If your compiler gives cast warnings it means you might be doing something you don't want to do, so that's why it's better to do an explicit cast.


It is not casting to void*, it is casting to void**. This is a different type.


I was replying to this...
Quote:
isn't a pointer conversion to void always legal

Share this post


Link to post
Share on other sites
deadimp    310
I'm not entirely sure if the question has been answered yet, but I compiled this with Dev-C++ (MinGW), and it didn't give me any warnings:
 void *a;
void **b=&a;
a=b;

"void*" can take any pointer type.
But, if you replace "a=b" with "b=a", it will tell you that there is an invalid conversion from "void*" to "void**". So "void**" can not take any arbitrary pointer type.

Share this post


Link to post
Share on other sites
jagguy    100
I am not really sure i still get this.

q) Is a VOID the same as void?

q) if you look at this in terns of an array. A
VOID* pVertices; //is an array

(void**)&pVertices //is a pointer to pointer like a 2-d array so you are re-casting this as another data type, so why not cast is as this
VOID** pVertices; //initially

it looks like we are giving space for an 1-D array then changing it to a 2-D array, that's why it look odd to me.

Share this post


Link to post
Share on other sites
ronkfist    100
Quote:
Original post by jagguy
q) Is a VOID the same as void?

probably, usually its defined in winnt.h

Quote:
Original post by jagguy
q) if you look at this in terns of an array. A
VOID* pVertices; //is an array

(void**)&pVertices //is a pointer to pointer like a 2-d array so you are re-casting this as another data type, so why not cast is as this
VOID** pVertices; //initially

it looks like we are giving space for an 1-D array then changing it to a 2-D array, that's why it look odd to me.


- it could be used as a 2-D array.
void **b;

- or as a pointer to a 1-D array.
void *a
void **b = &a;

Personally I don't see the point of using a pointer to a 1-D array tho, so try give us the definition of Lock().

Share this post


Link to post
Share on other sites
void*    292
Okay, the question hasn't been answered, so I figured I ought to do my namesake justice here.

The pVertices (clearly, a pointer to vertices) is cast to void** because the pointer itself may change.

But, since pVertices is void*, you must get the address of that variable so that you can cast it to a pointer-to-a-pointer (as has already been mentioned).

Here's the reason the third argument to Lock is void**: if it were void*, you wouldn't be able to change the pointer value. This will probably make more sense if you first consider the case where the argument is not a pointer type.

Let's say we have a function foo:

void foo(int a)
{
a = 0;
}


If you call foo(x) then print the value of x, you'll find that it doesn't actually change. This is because the change only exists within the scope of the function foo(), unless you pass the argument by reference or by pointer. So, if we had another function:

void bar(int* a)
{
*a = 0
}


then calling bar(&x) _would_ change x.

In the case where the location of the pointer might change, you would want to pass a pointer-to-a-pointer, so that any change to which pointer was being used could continue outside of the function's scope. The pointer itself may still point to the same address as the pointer being passed to the function (which is probably the case for this Lock() function) yet which pointer is doing so can be changed (and since it's a void**, the type of the underlying object itself could also change). An example:


void* global_verts;

bool foobar(void** pToP)
{
// you could append the values in the arguments to the global vertices
int size = length(global_verts) + length(*pToP); // assume length is a helper function to find the length of an array of vertices
void* newPtr = new Vertex[size];
gLen = length(global_verts);
for (i = 0; i < gLen; ++i) newPtr[i] = global_verts[i];
for (i = 0; i < length(*pToP); ++i) newPtr[i+gLen] = (*pToP)[i];

void* old_global = global_verts // (see edit below)
void* old_ptop = *pToP; // (see edit below)

// here, we change the global pointer to the new concatenation of vertices
global_verts = newPtr;
// and make sure that the argument gets updated, too
*pToP = global_verts;

// EDIT: fixed a memory leak (be careful when using pointers!)
delete [] old_global;
delete [] old_ptop; (I'm assuming that the argument had always been allocated using new [] -- make sure new and delete calls match)

return true;
}


[Edited by - void* on May 19, 2006 8:21:23 PM]

Share this post


Link to post
Share on other sites
deadimp    310
In all honesty, I don't see why you are declaring 'pVertices' as 'VOID*'. You might as well declare it as your vertex type (as Evil Steve stated) and save all the fun stuff for passing it off to IDirect3DVertexBuffer9::Lock() (well, DX 8 or 9).
Plus, I think it's a double pointer so that it can also set the value of the data that you pass off to the function.

NOTE: That's an interesting name, void*.

Share this post


Link to post
Share on other sites
pulpfist    528
Quote:

it looks like we are giving space for an 1-D array then changing it to a 2-D array, that's why it look odd to me.

Consider this allocator function:
(Im using char* for my illustration rather than void* since it is impossible to allocate void chunks)

void Alloc(char* ptr, int size)
{
ptr = new char[size];
}
char *my_cstring;
Alloc(my_cstring, 32);

Now this will not work, and it results in a memory leak.
Im not sure how to explain what happens here very well, but the way I see it, the compiler makes a copy of the ptr argument, and then that copy is allocated to the new memory. Obviously a disaster...

To make it work we can do like this:

void Alloc(char** ptr, int size)
{
*ptr = new char[size];
}
char *my_cstring;
Alloc(&my_cstring, 32);

Now this will work, and it does not result in a memory leak.
The way I see it, ptr is a pointer to the pointer that is to be allocated memory. The complier does basically the same as before, but this time a copy is made of the pointer that points to the actual pointer I want to allocate memory to. This solves the problem from the first example. I guess you can say that we play a little trick on the compiler so that it doesnt make a copy of the actual pointer.
Ofcourse, as long as the function doesnt change what the pointer points to, this conversion from * to ** is not necessary.

The price we pay for this little trick is a pretty nasty and non-intuitive syntax. Only God knows why MS dont use C++ references for this kind of thing.
It looks like the old boys is going to make the rules for another few years.

As you mentioned earlier, why not do this:

char **my_cstring;
Alloc(my_cstring, 32);

The compiler will probably accept this scenario, but the problem is that char** was not what I wanted. It is not the same as char*, and it can not be fed to printf or something similar.

[Edited by - pulpfist on May 19, 2006 11:17:43 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this