Because of opeator []
inline implementation. a[b]
actually is *(a + b)
So the first []
chooses the row and the second chooses the column.
So it is arr[m][n]
the same as stepOne = *(arr + M)
where M = m * n
and stepTwo = stepOne[n]
,
which is the same as *(stepOne + n)
. So after this chain we see what arr[m][n]
is the same as *(arr m*n + n)
To confirm what is true you can check this short program
int main()
{
char arr[10][15];
std::cout << sizeof(arr) << std::endl; //150
std::cout << sizeof(*arr) << std::endl; //15
std::cout << sizeof(arr[0]) << std::endl; //15
std::cout << sizeof(*arr[0]) << std::endl; //1
std::cout << sizeof(**arr) << std::endl; //1
std::cout << sizeof(arr[0][0]) << std::endl; //1
std::cout << arr << std::endl; //some number
std::cout << arr+1 << std::endl; //some number + 15
std::cout << &arr << std::endl; //some number
std::cout << &arr+1 << std::endl; //some number + 150
return 0;
}
+---+---+---+---+---+---+---+
This is matrix: | E | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
| | | | | | | |
+---+---+---+---+---+---+---+
I marked entry letter E. Lets say this is int M[6][7]
. So lets go reverse way.
&M
- pointer to matrix. If you increase or decrease it by one you will get on some other data, this is bad... because sizeof(M)
is the same as sizeof(int) * 7 * 6
&M[0]
pointer to the first row of matrix. If you increase it you will go to the next row, because sizeof(M[0])
is equals to sizeof(int) * 7
.
- So to get pointer to entry you need to do
&(M[0][0])
and sizeof(M[0][0])
is equals to sizeof(int)
.
So to make a graph out of all this:
+---+---+---+---+---+---+---+
M[0] ----> | E | | | | | | |
+---+---+---+---+---+---+---+
+---+
M[0][0] ----> | E |
+---+
I hope graph help because I'm not so good in explaining this stuff...
BTW One more thing, pointer to pointer not always a matrix.