(Self-answered Q&A - this matter keeps popping up)
I assume that the reader is aware of how pointer arithmetic works.
int arr[3] = {1,2,3};
int* ptr = arr;
...
*(ptr + i) = value;
Teachers/C books keep telling me I shouldn't use *(ptr + i)
like in the above example, because "pointers support array style indexing" and I should be using ptr[i] = value;
instead. No argument there - much easier to read.
But looking through the C standard, I find nothing called "array style indexing". In fact, the operator []
is not expecting the either operand to be an array, but instead a pointer or an integer!
6.5.2.1 Array subscripting
Constraints
One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.
Why does the array subscripting operator not expect an array? Is the standard wrong? Is my teacher/C book confused?
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:
Meaning that whenever you type
arr[i]
, the operandarr
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):
So whenever we type
arr[i]
, it actually gets silently replaced by*(arr+i)
. Wherearr
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 toarr[i]
. But don't write such code in real applications.