user2406944
user2406944

Reputation:

Changing values in an array from a pointer?

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

Answers (5)

addaon
addaon

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

Floris
Floris

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

Vlad from Moscow
Vlad from Moscow

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

Sebastian Redl
Sebastian Redl

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

Mike Seymour
Mike Seymour

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

Related Questions