• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1152
  • Last Modified:

How to cast a void pointer to a multi array pointer in ISO c++?

Hi everyone,

i have the following problem,  
I want to cast a void pointer to a pointer for a 2d-array with bounds. My code that does NOT work look like this:

double (*newArr)[(*border).grid][(*border).grid]=(double *[(*border).grid][(*border).grid]) (*border).Arr1;
where grid is a int, newArr is suppose to become the pointer to the 2d-array, Arr1 is a void pointer that in a structure pointed to by border and Arr1 points to the array that i really want to point to.

What should i write instead? please help!
0
Rawer
Asked:
Rawer
1 Solution
 
jkrCommented:
1st of all, array bounds need to be constants. 2nd, an array name itself is a pointer. So, if you have

double some_arr[20][30];

void* p = (void*) some_arr;

double*** pd = (double***) p;

The above line *really* looks confusing. Maybe you'd want to take a look at a matrix library like MTL (http://www.osl.iu.edu/research/mtl/) to make things a little simpler...

0
 
gugarioCommented:
You don't need the bounds when declaring a pointer to a matrix ( a 2d array).  Only when declaring the matrix itself. All you need is:

double ** newArray = (double **) Arr1;

You can then access elements in your array using something like:

double myDble = newarray[0][1];  // this will give you the double value in position (0,1)

hope this helps.

Gustavo.
0
 
RawerAuthor Commented:
jkr, how can I then access the elements? cuz it seg faults now...
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
RawerAuthor Commented:
when trying to access them like p[5][1] for example.
0
 
jkrCommented:
How *are* you currectly accessing it? Remember, it is a pointer to an array, so in the above you'd have to use

double some_arr[20][30];

void* p = (void*) some_arr;

double*** pd = (double***) p;

double d = (*pd)[5][1]
0
 
RogueAceCommented:
After doing some experimenting with this (frankly, I've never tried this before), here's what I found:

double I[10][10];

I[0][0]=1.0;
I[2][0]=2.0;
I[1][0]=1.5;

void* vp = (void*)I;

double* n=(double*)vp;
cout << n[0] << endl << n[10] << endl << n[20] << endl;

This will (believe it or not) output
1.0
1.5
2.0

However, doing it the way jkr says results in a segmentation fault, as Rawer found. I don't think it's logical even to declare pd as a double*** (double** should suffice, since it's a pointer (array) of double pointers (arrays)). However, this also segfaults.

The reason is subtle and annoying: C++ stores its multidimensional arrays in row major form. This means that a 3x3 matrix that looks like
1 2 3
4 5 6
7 8 9
is stored in memory as 1 2 3 4 5 6 7 8 9. So when I accessed n[10], I was really accessing n[1 * (rowsize) + 0] (I was sort of expecting this, which I why I did it that way).

The problem is, a statically-sized multidimensional array is not really an array of arrays. The second problem is, if you try to say n[1][0], it won't compile...because to the compiler, a double pointer is different from a multidimensional array of doubles. But if you say something like double n[10][10] = (double*) vp, that is an incorrect initialization acording to the compiler.

Here is what you probably should do. Instead of using a multidimensional array, do something like this:

double** dpp = new double*[numRows];

for(unsigned int c=0;c<numRows;c++)
  (*dpp)=new double[numCols];

Then you really DO have a double**, and the code will work the way jkr says it will. If this looks as dodgy to you as it does to me, you might want to seriously consider jkr's suggestion of using matrix templates. If you want to do one yourself, a vector of vectors (the STL vector is in c++ header <vector>) is a good quick way to implement one.

Good luck!
0
 
efnCommented:
Assuming you have a real two-dimensional array and not an array of pointers, I believe RogueAce's idea is the only one posted so far that will work, but it requires copying the whole array.  You can avoid that with a bit of pointer magic:  you would still have an array of pointers, but you can set them to point to the right places in the original data, so you don't have to copy it.  Something like this:

      double originalArray[10][20];
      void* pVoid = originalArray;
      int rows = 10;
      int columns = 20;
      double** pseudoArray = new double*[rows];
      double* pDouble = static_cast<double*>(pVoid);
      for (int ndx = 0; ndx < rows; ++ndx)
      {
            pseudoArray[ndx] = pDouble + (ndx * columns);
      }

--efn
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now