tags:

views:

84

answers:

2

Hi guys! I was given a question from my prof. that to use a void pointer to create a dynamic 2D array rather than int pointer due to the data type is more general.

But I've no idea how to create by using -> void***m // data type is void* pointer

Anyone can give an example on this? Appreciate your answer, many thanks!

A: 

Hi Zhen,

If I had to do it that way, the approach I'd take would be to allocate the memory using

new unsigned char[<max size in bytes>]

Then I'd create a templated class to access the array. Something like:

template<class ElementType, int numBytes>
class DynamicArray
{
public: 
    DynamicArray(unsigned char* buffer);
    ElementType& Get(long index);
    void Set(long index, const ElementType &element);
private:
    ElementType* m_array;
};

In your templated implementations of the getter/setter methods you'd simply access m_array. You'd check that index was valid by multiplying it by sizeof(ElementType) and then verifying that it was less than numBytes.

The constructor would simply cast buffer to ElementType* and assign that to m_array;

You could then allocate the array using bytes and then access it in different formats thusly:

unsigned char* buffer = new unsigned char(1000);
DynamicArray<long, 1000> longArray(buffer);
long val = 10;
longArray.Set(0, val);
longArray.Get(0);

DynamicArray<short, 1000> shortArray(buffer);
short firstTwoBytes = shortArray.Get(0);
etc.

The reason I would do it this way is that it gives you maximum compile-time type safety. That's one thing that C++ templates are really good at. You can use the same buffer with multiple instances of this templated class as demonstrated by the code above. I didn't try to compile this, so I apologize if there are any syntax errors.

BTW, you could use operator overloads to make the array accessors look like they were a 'C' array. See the STL's "vector" class for an example.

David Gladfelter
That's great! Thanks for your explanation!
zhen
+2  A: 

An array reference is pretty simple.

Lets say that B is the base address of the array (the starting address), S is the size of an element and I0 is an index into an array.

In the case of a one dimensional array, the address of an element is:

B + (S * I0)

You can extend this to multiple dimensions, but now you need to know the other dimensions of the array. Lets say you have a two dimensional array with dimensions D1, D0, and indices I0, I1 the address of an element is:

B + (D1 * I1 * S) + (S * I0)

A three dimensional array would be

B + (D2 * I2) * (D1 * I1 * S) + (S * I0)

and so on.

In the case of your void pointer, for a two dimensional array of int:

int D1 = 10, D0 = 20, I1 = 5, I0 = 5;
void * base;

base = malloc((D1 * D0) * sizeof(int));
int value = *((char*)base + (D1 * I1 * sizeof(int)) + (sizeof(int) * I0));

Note that I had to cast the void pointer to char* so that pointer arithmetic would be done in sizeof() units.

Even though this might be general, I don't think I'd use it much ;-) It does help to understand how array indexing works, though.

Richard Pennington