void type?

Started by
12 comments, last by pulpfist 17 years, 11 months ago
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().
Advertisement
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 = global_verts;    for (i = 0; i < length(*pToP); ++i) newPtr[i+gLen] = (*pToP);    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]
Greenspun's Tenth Rule of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp."
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*.
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
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]

This topic is closed to new replies.

Advertisement