Let's say I declare and initialize the following multi-dimensional array in C++:
unsigned a[3][4] = {
{12, 6, 3, 2},
{9, 13, 7, 0},
{7, 4, 8, 5}
};
After which I execute this code:
cout << a << endl; // output: 0x7fff5afc5bc0
cout << a + 1 << endl; // output: 0x7fff5f0afbd0
cout << *a << endl; // output: 0x7fff5afc5bc0
cout << *a + 1 << endl; // output: 0x7fff5f0afbc4
I just don't understand what is happening here.
a is the address of the first element, right? In single-dimensional arrays, *a should be the value of the first element, but instead it's the same as a?! What does *a even mean in this context?
Why is a + 1 different from *a + 1?
You should try and find some good documentation about pointers, arrays, and array-to-pointer decay. In your case, unsigned a[3][4] is a bi-dimensional array of type unsigned [3][4]. Whenever you refer to it as a, it decays to a pointer to unsigned[4], so the decayed type of a is unsigned (*)[4]. Therefore dereferencing it gives you an array, so *a is the array [12, 6, 3, 2] (technically it's the pointer to the first element into the array).
Now, a+1 means "increment the pointer to unsigned[4] by 1", in your case it "jumps" 4 unsigneds in the memory, so now a+1 points to the "row" indexed by 1 in your example. Dereferencing it *(a+1) yields the array itself ([9,13,7,0]) (i.e. the pointer to the first element of it), and dereferencing again gives you the first element, i.e. **(a+1) equals 9.
On the other hand, *a+1 first dereferences a, so you get the first row, i.e. [12,6,3,2] (again, technically the pointer to the first element of this row). You then increment it by one, so you end up pointing at the element 6. Dereferencing it again, *(*a+1), yields 6.
It may be helpful to define a equivalently as
typedef unsigned T[4]; // or (C++11) using T = unsigned[4];
T a[3]; // Now it's a bit more clear how dereferencing works
Two dimensional array is array of array.
You can visualize a as
a = { a[0], a[1], a[2]}
and a[0], a[1], a[2] as
a[0] = { a[0][0], a[0][1], a[0][2], a[0][3]};
a[1] = { a[1][0], a[1][1], a[1][2], a[1][3]};
a[1] = { a[2][0], a[2][1], a[2][2], a[2][3]};
Analysis of your first question
ais the address of the first element, right?
Yes a is the address of the first element, and first element of a is a[0] which is the address of the first element of a[0][0].
*a should be the value of the first element, but instead it's the same as a?
Yes *a should be the value of the first element that refer a[0]. And we see a[0] is the address of a[0][0] so as a . Thus *a have same value as a which is the address of a[0][0].
What does *a even mean in this context?
Previously answered, *a is the address of first arrays first element a[0][0], and *(a+1) is the address of second arrays first element a[1][0].
And analysis of your second question
Why is
a + 1different from*a + 1?
At this time perhaps you can answer your owns question.
a is the address of a[0] then
a+1 is the address of a[1] which hold address of a[1][0].
You can print the value by
cout<<**(a+1)<<endl; // 9
Other way *a is the value of a[0] which is the address of a[0][0].
So *a+1 is the address of a[0][1]. You can print the value as
cout<<*(*a+1)<<endl; // 6
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