Array declaration:
int arr [ ]={34, 65, 23, 75, 76, 33};
Four notations: (consider i=0)
arr[i]
and
*(arr+i)
and
*(i+arr)
and
i[arr]
Array declaration:
int arr [ ]={34, 65, 23, 75, 76, 33};
Four notations: (consider i=0)
arr[i]
and
*(arr+i)
and
*(i+arr)
and
i[arr]
Lets take a look at how your array is laid out in memory:
low address high address | | v v +----+----+----+----+----+----+ | 34 | 65 | 23 | 75 | 76 | 33 | +----+----+----+----+----+----+ ^ ^ ^ ^ | | | ...etc | | | | | arr[2] | | | arr[1] | arr[0]
That the first elements is arr[0]
, the second arr[1]
is pretty clear, that's what everybody learns. What is less clear is that the compiler actually translates an expression such as arr[i]
to *(arr + i)
.
What *(arr + i)
does is first get a pointer to the first element, then do pointer arithmetic to get a pointer to the wanted element at index i
, and then dereference the pointer to get its value.
Due to the commutative property of addition, the expression *(arr + i)
is equal to *(i + arr)
which due to the above mentioned translation is equal to i[arr]
.
The equivalence of arr[i]
and *(arr + i)
is also what's behind the decay of an array to a pointer to its first element.
The pointer to the arrays first element would be &arr[0]
. Now we know that arr[0]
should be equal to *(arr + 0)
which means &arr[0]
has to be equal to &*(arr + 0)
. Adding zero to anything is a no-op, so leading to the expression &*(arr)
. Parentheses with only one term and no operator can also be removed, leaving &*arr
. And lastly the address-of and dereference operator are each other opposites and cancel out each other, leaving us with simply arr
. So &arr[0]
is equal to arr
.
Each element in the array, have a position in memory. The positions in the arrays are sequential. The arrays in C are pointers and always point the first direction on memory for the collection (first element of the array).
arr[i] => Gets value of "i-position" in the array. It is the same that arr[i] = *(arr + i)
*(arr+i) => Gets value that is in memory by adding the position in memory that point arr
and i value
.
*(i+arr) => Is the same that *(arr+i)
. The sum is commutative.
i[arr] => Is the same that *(i+arr)
. It's another way of representing.
They are the same because the C language specification says so. Read n1570
The notation a[i]
is syntactic sugar for *(a+i)
.
The first one is mathematical syntax (symbolics closer of what human brain is educated with) while the second one corresponds directly to one assembler instruction.
On the other hand *(a+i)=*(i+a)=i[a]
because the arithmetic of pointers is commutative.
It works because an array variable in C (i.e. arr in your example) is just a pointer to the beginning of an array of memory locations. A pointer is number which represents the address of a specific memory location. When you put and '*' in front of a pointer, it means "give me the data in that memory location".
These are the same because of how the array subscript operator []
is defined.
From sectino 6.5.2.1 of the C standard:
2 A postfix expression followed by an expression in square brackets
[]
is a subscripted designation of an element of an array object. The definition of the subscript operator[]
is thatE1[E2]
is identical to(*((E1)+(E2)))
. Because of the conversion rules that apply to the binary+
operator, ifE1
is an array object (equivalently, a pointer to the initial element of an array object) andE2
is an integer,E1[E2]
designates theE2
-th element ofE1
(counting from zero).
The expression arr[i]
in your example is of the form E1[E2]
. Because the standard states that this is the same as *(E1+E2)
that means that arr[i]
is the same as *(arr + i)
.
Because of the commutative property of addition, *(arr + i)
is the same as *(i + arr)
. Applying the equivalence rule above to this expression gives i[arr]
.
So in short, those 4 expressions are equivalent because of how the standard defines array subscripting and because of the commutative property of addition.