Things to remember:
- Name of the array is the address of its first element
So, as the array name is a, then, printing a would give you the address of a[0] (which is also the address of the array too) i.e. you will get the values of &a[0] (same as a) and &a to be the same
Now, you are aware that a and &a[0] refer to the first element, you can dereference the first element in 3 ways:-
*a *(&a[0]) a[0] - Note that internally, this gets transformed into: *(a+0)
Things to remember:
2. Adding an integer to a pointer takes the pointer to the next element
Here, &a points to the address of the whole array. Although the value of &a is the same as &a[0] and a, but, it is a pointer to the array, not pointer to the first element. So, if you add 1 to &a i.e. &a + 1, you'll go beyond this array.
SImilarly, as &a[0] and a are pointers to the first element, adding 1 to them will give you the next element of the array (if there are more than 1 items defined in the array). i.e. (a+1) and &a[0] + 1 point to the next element from the first element. Now, for dereferencing them, you can use:
*(a+1) *(&a[0] +1) a[1] - Note that internally, this gets transformed into: *(a+1)
Adding more information to remove the following doubt:
If, as this answer states, the name of the array were the address of its first element, then &a would be the address of the address of the first element.
The answer to this doubt is both No and Yes.
- No because there is nothing like address of the address.
- For understanding yes, consider the following situation:
Imagine that you have 10 boxes of chocolates and each box contains 5 chocolates (fitted in a line inside the box) and that the boxes are lined up.

Ok, enough chocolates to explain.
Here, So, boxes represent arrays of chocolates. Thus, we have with us 5 boxes of 5 chocolates each. The declaration for that would be:
Translating it to C, just assume that a is an array with 5 numbers.
-Now, if I ask you to tell me the location of the first box, then, you will refer to it as &a. If I ask you to get me the location of second box, then, you'll refer to it as &a +1.
- If I ask you to get me the location of first chocolate in the first box, then you'll refer to it as
&a[0] or (a+0) or a. - If I ask you to get me the location of second chocolate in the first box, then you'll refer to it as
&a[1] or (a+1) or a+1. Note: In (a+1), as a is the name of the array, it is the address of the first element, which is an integer. So, increasing a by 1, means the address of the second element. - If I ask you to get me the location of the second box of chocolates, then, you'll refer to it as
(&a+1) - If I ask you to get me the location of the first chocolate in the second box of chocolates, then, you'll refer to it as
*(&a+1) or *((&a+1) + 0) - If I ask you to get me the location of the third chocolate in the second box of chocolates, then, you'll refer to it as
(*(&a+1))+2
printfare invalid.%pis the correct specifier for pointers (you'd have to cast tovoid*). The only valid one is the 5th, since*ais indeed anint.&ais notint**. It isint(*)[5]which is something completely diffent.p->dataversusp->p->data. In one case the data is at one hop for the other at two hops. You need to understand that arrays are not pointers in C.