tags:

views:

169

answers:

7

Does anyone know how to use a void pointer to generate a 2D array rather than an int pointer?

For integer pointer, I do as follow:

int **m;

m = new int* [row];     
for(int i=0; i< row; i++)     
        m[i] = new int[col];

for (int i = 0; i < row; i++)
       for (int j = 0; j < col; j++)
             m[i][j] = rand () % 10;

What if the pointer type is void***m?

How can I define the storage like int? eg.(m = new int* [row];)

Thanks for your help.


Please allow me to specify my question clearer, I'm given these:

class Matrix
{
   public:
           Matrix();
           Matrix(int,int);

           void printMatrix();

   private:
           int row;
           int col;
           void***m;
           void initMatrix();      // Initialize the storage for row and column
           void generateMatrix (); // construct a 2D array
}
A: 

You can't. You need to know the size of the elements if you're responsible for creating the array. With a void *, you don't know anything about what it points to. You'd have to have the caller supply you with a size argument or something.

Edit: Perhaps the third * is the key: Is he asking you to create a two-dimensional array of void *, perhaps? After all, void * is a type just as much as int is. Where you say new int[col] you should be able to say new void * [col]. You didn't show enough of your code for me to really get how you were doing it, but if it was working with int**, then it should work with void*** very nearly by just doing a search-and-replace on int => void *.

T.J. Crowder
I was given a class as follow:class Matrix{ private: int row; int col; void***m;}What if I need to generate a 2x2 array?
zhen
Can you please provide an example how to create a 2D dynamic array by using void* pointer? Thanks!
zhen
Perhaps you need to figure out the answer to the question given to you in class rather than asking for someone else to solve it for you?Anyhow, you can't allocate a "dynamic" array - there's no such thing (unless you're allocating something like a std::vector).
Steve Lacey
+1  A: 

With the snippet you posted in a comment to another answer, it's a bit easier to help you.

class Matrix {
    private:
    int row;
    int col;
    void** m;
}

Code to initialize the rows of the table could be something like this:

m = malloc(sizeof(int*) * row);

Hopefully you can use this to solve the rest of your homework, yourself.

gnud
+5  A: 

Your question is probably best answered by an explanation of what void means.

void basically denotes the absence of a type. As a consequence of this, you cannot tell the compiler to create an object of type void, e.g. with the following statements:

  • new void
  • new void[...]

The meaning of these expressions is roughly the following: "create something", or "create an array of somethings" respectively. This is clearly not a precise enough statement for the compiler.

void* (pointer to void) however is permitted because pointers are fundamentally always the same thing to the compiler: a memory address of another object. You can think of a pointer as some kind of arrow pointing to something. If you're working with a pointer, the compiler sees that arrow, and not the actual thing it points at. Therefore the compiler doesn't care that the "target type" is void.

The consequence of this, however, is that you cannot dereference a void* (pointer to void), because then you make the compiler effectively look at the pointed-to thing, which would be a void value, which doesn't make any sense to the compiler.

Summary:

1) You cannot create an array of type void, as in new void[...].

2) You can create a pointer to void (void*), or even a pointer to a pointer to void* (void**).

3) You cannot dereference a void* pointer (but you can dereference a void** pointer).

Conclusions:

4) You can create an int* array and let a void* refer to it:

int** m;
// ... (create the dangling array as in the OP's code and let m point to it)
void* v = (void*)m;

(See the comments below on why a void* is used here instead of void**!)

5) Because of statement #3, all you can reasonably do with such a pointer is pass it around, but you cannot work on the array's actual content. In order to do this, you need to type-cast it back to the correct data type:

int **m2 = (int**)v;
stakx
In `void **v = (void **)m;`, `v` is not a `void` pointer. Did you mean `void *v = (void *)m;`?
Alok
True, statement #4 and the code example don't fit together nicely. I'll correct this.
stakx
It's still weird. Why do you write `void** v = (void**)m;` instead of `void* v = m;`? (notice http://stackoverflow.com/questions/560845/what-are-the-often-misunderstood-concepts-in-c/566416#566416 )
Johannes Schaub - litb
Thank you for the hint! I just learnt something new from the post you linked to. `void*` is indeed better than `void**`, because it makes it clearer that one's not supposed to dereference the pointer and work with the target object. Thanks again!
stakx
A: 

Since every pointer type is implicitly convertible into a void*, you do as you did with the int* and assign that to the void*.

Where is the problem? Am I missing something?

sbi
+1  A: 

a void* is a pointer to some unspecified type. Of course, it's a happy accident that in the common case a pointer is exactly the same size as an int, so there really isn't anything preventing you from writing:

int **m;

m = new int* [row];     
for(int i=0; i< row; i++)     
    m[i] = new int[col];

for (int i = 0; i < row; i++)
   for (int j = 0; j < col; j++)
         m[i][j] = rand () % 10;

void ***v = (void ***)m; // v is a 2-d array of void* pointers now!

Of course, I'm not sure why you'd want a void*** array for a Matrix class. perhaps a custom numeric datatype?

Jimmy
*Wow* will that break on some architectures. I would never, ever recommend assuming `void*` is the same size as `int`.
T.J. Crowder
Voted up for using the questions content and adding a simple type conversion at the end.
Chad
@T.J Crowder, yeah, it isn't really anythign I'm advocating, but given the constraints of the problem I can't really imagine what the prof wants.
Jimmy
Casting an `int**` to a `void***` looks pretty dangerous.
strager
Depends on the compiler setting. In Visual Studio you can specify in 64 bit mode if you wish the pointer size to be 8bytes or stay at 4 bytes. Though I see nothing wrong with this answer with assuming void* to be the same size as int*. Although it just depends on the compiler setting and here I would assert that you assume int void* to be the same size as int.
Chad
@Jimmy, I appreciate your help! I was given a task by my prof. that I need to construct a Matrix by using a given void***m pointer rather than int pointer. In addition, if void ***v = (void ***)m; how can i dereferencing V? What if I want to output the 2D array?
zhen
A: 

The closest answer I can think of is the following one. You can create a 2D array as a vector of ints, and then transferr it as void *. This is very similar to how it is stored in memory.

const unsigned int MaxRow = 10;
const unsigned int MaxColumn = 10;

void print(void * m)
{
    int * matrix = (int *) m;

    for(unsigned int i = 0; i < MaxRow; ++i) {
        for(unsigned int j = 0; j < MaxColumn; ++j) {
            std::printf( "%03d ", matrix[ ( i * MaxColumn ) + j ] );
        }

        std::printf( "\n" );
    }
}

int main()
{
    // Create
    int * matrix = new int[ MaxRow * MaxColumn ];

    for(unsigned int i = 0; i < MaxRow; ++i) {
        for(unsigned int j = 0; j < MaxColumn; ++j) {
            matrix[ ( i * MaxColumn ) + j ] = ( i * MaxColumn ) + j;
        }
    }

    // Show
    print( matrix );

    delete[] matrix;
    return 0;
}
Baltasarq
A: 

Let me specify my question clearer!

I'm given

class Matrix
{
   public:
           Matrix();
           Matrix(int,int);

           void printMatrix();

   private:
           int row;
           int col;
           void***m;
           void initMatrix();      // Initialize the storage for row and column
           void generateMatrix(); // construct a 2D array
}
zhen
Please edit the original question. Posts like this are meant for possible *answers*.
strager
And frankly, that doesn't make it much clearer.
T.J. Crowder