You should indeed be using ptr[i]
over *(ptr + i)
for readability reasons. But apart from that, the []
operator is, strictly speaking, actually never used with an array operand.
Arrays, when used in an expression, always “decay” into a pointer to the first element (with some exceptions). C17 6.3.2.1/3, emphasis mine:
Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
Meaning that whenever you type arr[i]
, the operand arr
gets replaced by a pointer to the first element inside that array. This is informally referred to as “array decaying”. More info here: What is array decaying?
So whenever you use the []
operator, you use it on a pointer. Always.
The C standard says that this operator is guaranteed to be equivalent to the pointer arithmetic (C17 6.5.2.1/2):
The definition of the subscript operator
[]
is thatE1[E2]
is identical to(*((E1)+(E2)))
.
So whenever we type arr[i]
, it actually gets silently replaced by *(arr+i)
. Where arr
is still a pointer to the first element.
And this is why the description you quoted tells you that either operand could be a pointer and the other an integer. Because obviously it doesn’t matter if we type *(arr+i)
or *(i+arr)
– that’s equivalent code.
Which in turn allows us to write obfuscated “joke” code like i[arr]
, which is actually valid C and fully equivalent to arr[i]
. But don’t write such code in real applications.