You misunderstand.
A 2D array is a special shorthand syntax for indexing a 1D array as if it were a 2D array.
{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }
Appears in memory as:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }
But the compiler knows that the outer dimension is three elements long, so it can eyeball it like this:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }
Now, when you ask for an element, say a[ 2 ][ 1 ], it knows that you mean the third group (index == 2 --> third group) and the second element in that group.
Unfortunately, you can only pass variable-sized multidimensional arrays to a function where any dimension may vary in size by using templates -- and this can bloat code quickly.
I recommend a combined approach.
First, we need to calculate the linear index of an element in a multidimensional array.
1 2 3 4 5 6 7 8 9 10
|
size_t index_2d( size_t rows, size_t cols, size_t row, size_t col )
{
// You don't have to check this stuff... and how you do depends on you.
// Here I just throw an exception, but you can return (size_t)(-1) or whatever
// you think effective.
if ((row > rows) or (col > cols)) throw 1;
// Here's our equation
return (row * cols) + col;
}
|
C-style: playing compiler
Here is the function that does all the work.
This is the kind of function you want to write no matter what.
However, you must write it as if you were the compiler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
void my_fn(
// Here is the information the compiler knows about a 2D array:
int a[], // address of first element
size_t rows, // number of elements per major dimension
size_t cols ) // number of elements per minor dimension
{
// In this example function, I wish to look at each element in the array
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
{
size_t index = index_2d( a, rows, cols, r, c );
// Now I can access the element:
a[ index ] *= 5;
}
}
}
|
C++ style: all the fancy stuff to make it painless
What this is is a template function that converts a painless function call into the not-so-friendly function call to the function above.
Ideally, it should be compiled away so that there is absolutely no code bloat whatsoever.
1 2 3 4 5
|
template <size_t Rows, size_t Cols> inline
void my_fn( int (&a)[ Rows ][ Cols ] )
{
return my_fn( &(a[0][0]), Rows, Cols );
}
|
Remember, you'll need to add any additional arguments to the C-style function to this C++ function as well.
Now, life is easy for the
caller:
1 2 3 4 5 6 7 8 9 10
|
int main()
{
int M1[ 3 ][ 4 ];
int M2[ 5 ][ 7 ];
my_fn( M1 );
my_fn( M2 );
...
}
|
Hope this helps.