Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2D-array as argument to function

Tags:

c++

Why can't you declare a 2D array argument in a function as you do with a normal array?

 void F(int bar[]){} //Ok
 void Fo(int bar[][]) //Not ok
 void Foo(int bar[][SIZE]) //Ok

Why is it needed to declare the size for the column?

like image 878
Carlj901 Avatar asked Sep 29 '12 12:09

Carlj901


People also ask

Can a 2D array be passed to a function how?

We can pass the 2D array as an argument to the function in C in two ways; by passing the entire array as an argument, or passing the array as a dynamic pointer to the function.

How do you pass an array as functions arguments?

To pass an entire array to a function, only the name of the array is passed as an argument. result = calculateSum(num); However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.


1 Answers

Static Arrays:

You seem not to have got the point completely. I thought to try to explain it somewhat. As some of the above answers describe, a 2D Array in C++ is stored in memory as a 1D Array.

int arr[3][4] ;   //consider numbers starting from zero are stored in it

Looks somewhat like this in Memory.

1000    //ignore this for some moments       1011  
^                                             ^
^                                             ^

0   1   2   3   4   5   6   7   8   9   10   11
|------------|  |-----------|   |-------------|
  First Array    Second Array     Third Array

|----------------------------------------------|    
                Larger 2D Array

Consider that here, the Bigger 2D Array is stored as contiguous memory units. It consists of total 12 elements, from 0 to 11. Rows are 3 and columns are 4. If you want to access the third array, you need to skip the whole first and second arrays. That is, you need to skip elements equal to the number of your cols multiplied by how many arrays you want skip. It comes out to be cols * 2.

Now when you specify the dimensions to access any single index of the array, you need to tell the compiler beforehand exactly how much elements to skip. So you give it the exact number of cols to perform the rest of the calculation.

So how does it perform the calculation? Let us say it works on the column major order, that is, it needs to know the number of columns to skip. When you specify one element of this array as...

arr[i][j] ;

Compiler performs this calculation automatically.

Base Address + (i * cols + j) ;

Let us try the formula for one index to test its veracity. We want to access the 3rd element of the 2nd Array. We would do it like this...

arr[1][2] ;   //access third element of second array

We put it in the formula...

  1000 + ( 1 * 4 + 2 )
= 1000 + ( 6 )
= 1006   //destination address

And we reach at the address 1006 where 6 is located. In a nutshell, we need to tell the compiler the number of cols for this calculation. So we send it as a parameter in a function.

If we are working on a 3D Array, like this...

int arr[ROWS][COLS][HEIGHT] ;

We would have to send it the last two dimensions of the array in a function.

void myFunction (int arr[][COLS][HEIGHT]) ;

The formula now would become this..

Base Address + ( (i * cols * height) + (j * height) + k )  ;

To access it like this...

arr[i][j][k] ;

COLS tell the compiler to skip the number of 2D Array, and HEIGHT tells it to skip the number of 1D Arrays. And so on and so forth for any dimension.

Dynamic Arrays:

As you ask about different behavior in case of dynamic arrays which are declared thus..

int ** arr ;

Compiler treats them differently, because each index of a Dynamic 2D Array consists of an address to another 1D Array. They may or may not be present on contiguous locations on heap. Their elements are accessed by their respective pointers. The dynamic counterpart of our static array above would look somewhat like this.

1000  //2D Pointer
^
^
2000       2001     2002
^          ^        ^
^          ^        ^
0          4        8
1          5        9
2          6        10
3          7        11

1st ptr  2nd ptr   3rd ptr

Suppose this is the situation. Here the 2D Pointer or Array on the location 1000. It hold the address to 2000 which itself holds address of a memory location. Here pointer arithmetic is done by the compiler by virtue of which it judges the correct location of an element.

To allocate memory to 2D Pointer, we do it..

arr = new int *[3] ;

And to allocate memory to each of its index pointer, this way..

for (auto i = 0 ; i < 3 ; ++i)
  arr[i] = new int [4] ;

At the end, each ptr of the 2D Array is itself an array. To access an element you do...

arr[i][j] ;

Compiler does this...

*( *(arr + i) + j ) ;
   |---------|
     1st step
|------------------|
      2nd step

In the first step, the 2D Array gets dereferenced to its appropriate 1D Array and in the second step, the 1D Array gets dereferenced to reach at the appropriate index. That is the reason why Dynamic 2D Arrays are sent to the function without any mention of their row or column.

Note: Many details have been ignored and many things supposed in the description, especially the memory mapping just to give you an idea.

like image 114
Coding Mash Avatar answered Oct 04 '22 08:10

Coding Mash