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?
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With