Reputation:
I've been playing around with pointers to help get a better understanding. I have declared a
as a pointer to an array of integers of length 3 and b
as an array of integers of length 3. I then point a
at b
.
int main()
{
int (*a)[3];
int b[3] { 2, 4, 6 };
a = &b;
a[0][0] = 8;
// This prints out 8 and 8.
std::cout << a[0][0] << "\t" << b[0];
// This prints out 0x28fecc and 8.
std::cout << a[0] << "\t" << b[0];
return 0;
}
To access an element of b
through the pointer a
, I have to do a[0][0]
as if a were an array of arrays. This is compared to declaring a pointer to an array of integers using the new keyword where I can just output c[0]
.
int* c = new int[3] { 2, 4, 6 };
std::cout << c[0];
Why is this?
Many thanks, George
Upvotes: 4
Views: 162
Reputation: 1152
Declaration reflects use.
b
is declared as int b[3]
; you access (the first element of) it as b[0]
.
a
is declared as int (*a)[3]
; the equivalent access would be (*a)[0]
.
If you break down that "equivalent access", you can see that it has two operations. First, it uses the dereference operator "unary star" -- *a
. a itself, remember, is a pointer. Dereferencing a returns the value pointed to. So once a = &b
, then *a == b
.
So what's the deal with a[0][0]
? Well, the array access operator []
actually works on general pointers (and, to make things weirder, arrays "decay" to pointers). a[N]
is defined in C to be exactly the same as *(a + N)
; so a[0]
is the *a
that we already discussed. Basically, using a[0][0]
in this context instead of (*a)[0]
is using a pun based on the definition of operator []
to hide that declaration should reflect use.
Upvotes: 0
Reputation: 46375
The normal declaration of a
would be
int *a;
Then you could use
a = b;
std::cout << a[0];
Will print
8
Upvotes: 1
Reputation: 310990
It is because you defined another type. Consider one more the statement
int* c = new int[3] { 2, 4, 6 };
In the left side you use int *c. So you could write the same for your local array
int *a;
int b[3] { 2, 4, 6 };
a = b;
In this case you could access each element of the array simply by using one subscripting:
a[0] = 8;
In this expression statement
a = b;
array b is implicitly converted to a pointer to its first element, that is subexpression b in the right side has type int *
Upvotes: 0
Reputation: 71989
a
is a pointer to a single array, so you really should do (*a)[0]
. And when you do a[0]
, that's the same thing as *a
, so you get the array, which in the output decays to a pointer, which is why you see an address printed.
Whereas c
is a pointer to an integer, and known to point to the first element of an array, so simple array notation works.
Upvotes: 1
Reputation: 254461
I have to do
a[0][0]
as if a was an array of arrays.
Indeed, a
is a pointer to an array, so the array itself is *a
, and the first element of the array would be (*a)[0]
or, equivalently, a[0][0]
.
You probably want a
to be a pointer to the first element of the array (just as c
is a pointer to the first element of a dynamic array):
int * a = b;
and now a[i]
will be element i
of the array as expected.
Upvotes: 4