Reputation: 51
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[101][101];
a[2][0]=10;
cout<<a+2<<endl;
cout<<*(a+2)<<endl;
cout<<*(*(a+2));
return 0;
}
Why are the values of a+2
and *(a+2)
same?
Thanks in advance!
Upvotes: 2
Views: 15221
Reputation: 9705
I'll try to explain you how the memory is mapped by the compiler:
Let's consider a more pratical example multi-dimentional array:
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
You can execute the command
x/10w a
In GDB and look at the memory:
0x7fffffffe750: 1 2 3 4
0x7fffffffe760: 5 6 7 8
0x7fffffffe770: 9 0
Each element is stored in a int type (32 bit / 4 bytes). So the first element of the matrix has been stored in:
1) a[0][0] -> 0x7fffffffe750
2) a[0][1] -> 0x7fffffffe754
3) a[0][2] -> 0x7fffffffe758
4) a[1][0] -> 0x7fffffffe75c
5) a[1][1] -> 0x7fffffffe760
6) a[1][2] -> 0x7fffffffe764
7) a[2][0] -> 0x7fffffffe768
...
The command:
std::cout << a + 2 << '\n'
It will print the address 0x7fffffffe768 because of the pointer aritmetic: Type of a is int** so it's a pointer to pointers. a+2 is the a[0] (the first row) + 2. The result is a pointer to the third row.
*(a+2) deferences the third row, that's {7,8,9}
The third row is an array of int, that's a pointer to int.
Then the operator<< will print the value of that pointer.
Upvotes: 2
Reputation: 66371
The first element of an array is at the same location as the array itself - there is no "empty space" in an array.
In cout << a + 2
, a
is implicitly converted into a pointer to its first element, &a[0]
, and a + 2
is the location of a
's third element, &a[2]
.
In cout << *(a + 2)
, the array *(a + 2)
- that is, a[2]
- is converted into a pointer to its first element, &a[2][0]
.
Since the location of the third element of a
and the location of the first element of the third element of a
are the same, the output is the same.
Upvotes: 0
Reputation: 310960
If you have an array like this
T a[N];
then the name of the array is implicitly converted to pointer to its first element with rare exceptions (as for example using an array name in the sizeof
operator).
So for example in expression ( a + 2 )
a
is converted type T *
with value &a[0]
.
Relative to your example wuth array
int a[101][101];
in expression
a + 2
a is converted to rvalue of type int ( * )[101]
and points to the first "row" of the array. a + 2
points to the third "row" of the array. The type of the row is int[101]
Expression *(a+2)
gives this third row that has type int[101]
that is an array. And this array as it is used in an expression in turn is converted to pointer to its first element of type int *
.
It is the same starting address of the memory area occupied by the third row.
Only expression ( a + 2 )
has type int ( * )[101]
while expression *( a + 2 )
has type int *
. But the both yield the same value - starting address of the memory area occupied by the third row of the array a
.
Upvotes: 1
Reputation: 148890
a
is a 2D array, that means an array of arrays. But it decays to a pointer to an array when used in appropriate context. So:
a+2
, a
decays to a pointer to int arrays of size 101. When you pass is to an ostream, you get the address of the first element of this array, that is &(a[2][0])
*(a+2)
is by definition a[2]
: it is an array of size 101 that starts at a[2][0]
. It decays to a pointer to int, and when you pass it to an ostream you get the address of its first element, that is still &(a[2][0])
**(a+2)
is by definition a[2][0]
. When you pass it to an ostream you get its int value, here 10.But beware: a + 2
and a[2]
are both pointers to the same address (static_cast<void *>(a+2)
is the same as static_cast<void *>(a[2])
), but they are pointers to different types: first points to int array of size 101, latter to int.
Upvotes: 8
Reputation: 1740
A 2-dimensional array is an array of arrays, so it's stored like this in memory:
char v[2][3] = {{1,3,5},{5,10,2}};
Content: | 1 | 3 | 5 | 5 | 10 | 2
Address: v v+1 v+2 v+3 v+4 v+5
To access v[x][y], the compiler rewrites it as: *(v + y * M + x)
(where M is the second dimension specified)
For example, to access v[1][1], the compiler rewrites it as *(v + 1*3 + 1)
=> *(v + 4)
Be aware that this is not the same as a pointer to a pointer (char**). A pointer to a pointer is not an array: it contains and address to a memory cell, which contains another address.
To access a member of a 2-dimensional array using a pointer to a pointer, this is what is done:
char **p;
/* Initialize it */
char c = p[3][5];
p
;While to access the member via a traditional 2-dimensional array, these are the steps:
char p[10][10];
char c = p[3][5];
p
and sum the first offset (3), multiplied by the dimension of a row (10).Upvotes: 1