Thread: pointers to multidimensional arrays

1. pointers to multidimensional arrays

hi!
how would I declare a pointer to point to this array?
Code:
`int x[3][3][2]={1,2,3,2,3,4,5,7,9,1,2,3,2,3,4,5,7,9};`
Also is there a way to pass an array with variable dimension idexes to a function?
for example the function would take int x[3][3][2], but it also would be able to take
x[4][4][5] or x[2][3][56]?

2. Originally Posted by Luciferek
hi!
how would I declare a pointer to point to this array?
Code:
`int x[3][3][2]={1,2,3,2,3,4,5,7,9,1,2,3,2,3,4,5,7,9};`
Code:
`int (*)[3][2] p = x;`
But actually...

Also is there a way to pass an array with variable dimension idexes to a function?
for example the function would take int x[3][3][2], but it also would be able to take
x[4][4][5] or x[2][3][56]?
Yes. Use std::vector.
std::vector< std::vector< std::vector<int> > > >
3D-variable array.

3. Or you could 'flatten' the array. Here's something I wrote ages ago. It works for a 2D array, but you could arrange it for a 3D array too.
Code:
```#include<stdio.h>

void print ( int *pnum, int x, int y )
{
for ( int j=0; j<y; j++, printf("\n") )
{
for ( int i=0; i<x; i++ )
{
printf( "%d ", *pnum++ );
}
}
}

int main( void )
{
int test22[2][2] = {{9, 8}, {7, 6}};
int test23[2][3] = {{9, 8, 7}, {6, 5, 4}};
int test33[3][3] = {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}};
int test24[2][4] = {{9, 8, 7, 6}, {5, 4, 3, 2}};

printf( "Printing 2x2 matrix\n" );
print( &test22[0][0], 2, 2 );

printf( "\nPrinting 2x3 matrix\n" );
print( &test23[0][0], 3, 2 );

printf( "\nPrinting 3x3 matrix\n" );
print( &test33[0][0], 3, 3 );

printf( "\nPrinting 2x4 matrix\n" );
print( &test24[0][0], 4, 2 );

return 0;
}```

4. Except this is C++, not C, so dirty hacks that makes code hard to read should be avoided.

5. Hey! Not dirty! Not really anyway. I think it's a good exercise in learning the structure of multidimensional arrays.

6. Not if you work with vectors. Then it would mean undefined behavior, pretty much.
So it could be a good exercise for those who wish to learn more about native arrays or how the hardware works, but not the language or C++.
I don't really think it's a good idea...

7. So you figure beginners should gloss over the fundamentals in array allocation and structure and jump straight into vectors?! And not only a simple enough vector but a vector of a vector of a vector? Seriously? I don't really thing that is a good idea. Learning from the deep end is good, but not without some kind of demonstration of previous buoyancy.

8. Yeah, but if you bring in hacks and stepping over bounds like yours, they're in for a surprise later when they actually do use a vector.
So I'm suggesting that they "do it by the book." Don't step over bounds and like that, that can potentially cause undefined behavior. No "advanced" tricks.
No need to start with vectors right away. But if you treat arrays as you would vectors, then there's no problem with the transition later.
(And besides, some would argue that you should learn higher-level functionality before lower, aka C++-stuff such as vector before C-stye arrays. Both have their ups and downs.)

9. I'm still not convinced, but what the hey. It's a trick, but by no means advanced. If the OP was familiar with how arrays are stored in memory he would understand that by incrementing the position of the pointer to the 0th element of the multidimensional array you merely iterate through all elements. And with the array constrained by these bounds, as per parameters to the function, the pointer won't go over-board.

I dunno though. The fact that vectors are completely managed will add nothing to the learning experience. If you saw this, Elysia, when learning what would you think?
Code:
```#include <vector>
#include <iostream>

typedef std::vector<int>         array_type1;
typedef std::vector<array_type1> array_type2;
typedef std::vector<array_type2> array_type3;

void print( array_type3 myarr ) {
array_type3::iterator iter3 = myarr.begin();
array_type2::iterator iter2 = iter3->begin();
array_type1::iterator iter1 = iter2->begin();

for ( ; iter3!=myarr.end(); iter3++ ) {
for ( iter2=iter3->begin(); iter2!=iter3->end(); iter2++ ) {
for ( iter1=iter2->begin(); iter1!=iter2->end(); iter1++ ) {
std::cout<< *iter1 << " ";
}
std::cout<< "\n";
}
std::cout<< "\n\n";
}

}
int main( void ) {
array_type3 myarr( 3, array_type2( 4, array_type1( 5, 0 ) ) );
print( myarr );

return 0;
}```
? (Or is there a better way to print it? It's all I thought of, though I didn't put much effort into trying to make it better... Aside from [] operators, which I felt weren't necessary considering the OP's learning all about vectors anyway, so they might as well learn about iterators. )

Edit: I would have thought 'Holy crap. I'm outta here'.

10. I don't understand what's so dirty in that either. I don't think vector (dynamically allocated, resizable) is supposed to replace an array (on the stack, not resizable). A vector in this case would have a large memory overhead compared to the size of the contents, several small memory allocations and non-contiguous layout.

Something that I haven't used but that might be useful here is boost::multi_array

11. Code:
```#include <vector>
#include <iostream>

typedef std::vector<int>         array_1d;
typedef std::vector<array_type1> array_2d;
typedef std::vector<array_type2> array_3d;

void print(array_type3& myarr)
{
for (int d1 = 0; d1 < myarr.size(); d1++)
{
for (int d2 = 0; d2 < myarr[d1].size(); d2++)
{
for (int d3 = 0; d3 < myarr[d1][d2]; d3++)
{
std::cout<< myarr[d1][d2][d3] << " ";
}
std::cout<< "\n";
}
std::cout<< "\n\n";
}
}

int main()
{
array_3d myarr( 3, array_2d(4, array_1d(5, 0)) ); // int[3][4][5]
print(myarr);
return 0;
}```
Something along the lines of this, I guess.
The initialization syntax is the worst. But not too bad.
But with iterators, I agree with your edit.

12. Originally Posted by anon
I don't think vector (dynamically allocated, resizable) is supposed to replace an array (on the stack, not resizable).
Although, I never suggested this. I agree, there is a more flexible solution for constant arrays.
But in this case, the OP asked about varying numbers of dimensions and that is the work of dynamic arrays.
Unless you want to use template functions. That's possible too.

Something that I haven't used but that might be useful here is boost::multi_array
Hmmm. Although I would probably have used
boost::array< N, boost::array< N2, boost::array<N3, int> > >
I wasn't aware of multi_array...

13. I think the OP asked about passing various-sized arrays to functions, not about resizing the arrays. In which case twomer's solution (or the multi_array) would answer that.

14. Hmmm. Perhaps you're right.
boost::multi_array along with a template would probably be the best solution.

Code:
`template<int N> void myfunc(boost::multi_array<int, N>& myarr)`
I think that's right.

15. But the thing is all these solutions (vectors, boost::array, boost::multi_array), while they're all good solutions in themselves but, unless I'm mistaken, from the OP's point of view it might be like driving a Formula1 car when he knows how to drive a regular one[1]. Why introduce layers of complexity (templates, third party libraries and even standard libraries), when it's not required and frankly might only serve to confuse the OP. Somehow reminds me of this.

[1] From watching Top Gear I see it's not easy.

Popular pages Recent additions