views:

73

answers:

3

Hello, how can I pass multiarray into function through pointer with c++. I can do this with simple arrays

void Foo(int *arr) { }
int someArr[10];
Foo(someArr);

What about 2-dimensions array?

+2  A: 

It is more or less the same - except for the bits that are different, of course.

#include <stdio.h>

enum { DIM = 6 };

static void Bar(int arr[][DIM], int n)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < DIM; j++)
            printf("  %2d", arr[i][j]);
        putchar('\n');
    }
}

int anotherArr[][DIM] =
{
    {  1,  2,  3,  4,  5,  6 },
    {  6,  5,  4,  3,  2,  1 },
    {  0,  0,  0,  0,  0,  0 },
    { -1, -2, -3, -4, -5, -6 },
};

int main(void)
{
    Bar(anotherArr, 4);
    return(0);
}
Jonathan Leffler
Hm, why do you use enum for storing array dimension?
Ockonal
Can you do the same thing, but declare the parameter for Bar as a pointer instead of an array?
gnucom
@Ockonal: because I speak C better than C++.
Jonathan Leffler
@gnucom: yes, but you lose the benefit of compiler-calculated subscripts. See the answer by @functional.
Jonathan Leffler
+2  A: 

You can achieve what you want in this way:

void foo(int *array) { }

int column_size = 5;

int main() {
   int array[column_size][2];

   foo(&array[0][0]);

   return 0; 
}

although you should take care on how you read the elements from inside the foo function. In order to read the array[c][r] element you must do:

int element = *(array + c * column_size + r);

The general get element function is:

int get_element(int *array, int row, int column, int column_size)   {
  int element = *(array + row * column_size + column);
  return element;
}

So, if you have let's say an 2D array like int array[M][N] and you want to get the array[i][j] element you just call the function in this way:

getElement(&array[0][0], i, j, N)

Why does this work?

The reason the above function works can be clarified if you know how 2D arrays are saved in memory. The arrays are saved row-by-row, so let's say you have the following array:

int a[3][3] = {{1, 2, 4}, {5, 6, 7}, {8, 9, 10}};

let's assume an integer is 4 bytes and &a[0][0] corresponds to 0x10 memory address. Then 1 is saved in 0x10 memory address, 2 is saved in 0x14, ..., 7 is saved in 0x24 memory address, ... and 10 is saved in 0x30 memory address (see the following table).

*Memory*

Memory address => Value => Pointer pointing at this memory address

   0x10        =>   1   => &a[0][0]
   0x14        =>   2   => (&a[0][0] + 1) or (&a[0][1])
   0x18        =>   4   => (&a[0][0] + 2) or (&a[0][2])
   0x1c        =>   5   => (&a[0][0] + 3 * 1 + 0) or (&a[1][0])
   0x20        =>   6   => (&a[0][0] + 3 * 1 + 1) or (&a[1][1])
   0x24        =>   7   => (&a[0][0] + 3 * 1 + 1) or (&a[1][2])
   0x28        =>   8   => (&a[0][0] + 3 * 2 + 0) or (&a[2][0])
   0x2c        =>   9   => (&a[0][0] + 3 * 2 + 1) or (&a[2][1])
   0x30        =>   10  => (&a[0][0] + 3 * 2 + 2) or (&a[2][2])

Now when you have the following pointer:

int *pt = (&a[0][0] + 2);

the pt pointer will be pointing 2 elements after a[0][0]. So pt is pointing at a[0][2]. *pt will be equal to 4.

Now let's say you want to get the a[i][j] element. In order to get this element you need to move i * COLUMN_SIZE elements away in order to get in the correct row where the element is (each row has COLUMN_SIZE elements) and then you need to add j in order to get in the correct column.

If you want to get the a[2][1] (where COLUMN_SIZE = 3), then 2 * COLUMN_SIZE = 6 + 1 = 7. So in order to get the a[2][1] element you do *(&a[0][0] + 2 * 3 + 1) or *(&a[0][0] + 7).

For some great tutorials on pointers, have a look here: Stanford CS Ed Library.

But the function can then only refer to the array as a 1D array (vector), not as a correctly sized 2D array.
Jonathan Leffler
@jonathan-leffler Yeah, I knew about code you post. But the real question was about passing pointers, so @functional did what I wanted. Thanks.
Ockonal
@functional Great answer!
Ockonal
A: 
void Foo(int **arr) { }
int someArr[10][10];
Foo(someArr);
Bob Dale
That will crash horribly because it expects an array of pointers, and a 2D array is not the same as an array of pointers.
Jonathan Leffler
`someArr` is not of type `(int **)` but of type `(int (*)[10])`