All the solution are correct, but they don't highlight enough the magic word: "
Pointers arithmetic in C".
Google for it and you'll get all answers you need.
To understand why you can assign an array name to a pointer to array element types just consider that an array name is a pointer to its 0th element, so:
int arr[10]; int *p = arr;
Each time the compiler sees an array name creates a pointer to 0th element of the array, then use it to access the array.
Pointers Arithmetic allow sum and subtraction, and the operand must be a number. As special case you can subtract 2 pointers, pointing to same type, to get a number as result.
C language try to implement an abstract handling for pointers in the sense that they are managed as virtually accessing next value each increment or decrement. Of course real objects have a size that spans over many bytes so that to access adjacent values requires a memory displacement bigger that 1 for some types. This is silently handled by the compiler, that adds for each increment the required displacement.
I.e.
Type Start Address After increment
char 0x0021000 0x0021001 //Char is 1 byte
int 0x0021000 0x0021004 //int is 4 bytes
float 0x0021000 0x0021004 //float is 4 bytes
double 0x0021000 0x0021008 //double is 8 bytes
....
A pointer arithmetic operation can be described as:
address = (<type pointed> *)(((char *)p)+(number * sizeof(<type pointed>)))
Where the pointer p is casted to a char pointer to get 1 byte addressing, then we add our number multiplied by the size of the type pointed, than recast to point to our type.
This is valid for any kind of type, structures, unions, etc. In that case incrementing by one we will point to next structure.
Subtraction works the same way as sum, only the number is negative.
The special case of subtraction of two pointers gives the
integral number of objects of type pointed to between the two addresses.
You cannot sum two pointers. It is illegal.
Now the index operator, [], is equivalent to retrieve of value pointed by pointer after incrementing the pointer by the number in braces:
p[n] ==> *(p + N)
And this operation is conform to use of an array or a pointer on the basis of what we already said before about an array name (replaced by compiler with a pointer to its 0th element).
If you understood this you will understand your code... ;)