Today I found a piece of code where the program seems to have a bug, but works as expected:
This is a simplification of that code, which reproduces the same behavior:
int main()
{
int arreglo[] = { 0, 1, 2, 3 };
int indice = 0;
std::cout << arreglo[indice] << "\n";
indice++;
std::cout << arreglo[indice] << "\n";
indice++;
std::cout << indice[arreglo] << "\n";
indice++;
std::cout << arreglo[indice] << "\n";
}
Departure:
$ ./prueba
0
1
2
3
The question is: Why does the expression work indice[arreglo]
as if I were putting arreglo[indice]
, if they should be backwards?
According to section 5.2.1 Subscripting of this working draft of the C++ standard (apparently the specifications are sold by the ISO and are not publicly available) a is defined
E1[E2]
aswhere E1 and E2 are any expression
Then
Therefore it
indice[arreglo]
will be equivalent to:By simple commutative property of addition we can see that both expressions give the same
In this case
arreglo
according to section 4.2 Array-to-pointer conversion it is implicitly converted to the memory address of the first element of the array.There's really no such thing as an independent data type in C++: the array syntax is just an easy way to manipulate pointers.
More specifically,
matriz[indice]
it's actually a more readable form of*(matriz+indice)
. Hence, since addition is commutative, you get the same result withindice[matriz]
, or what amounts to the same*(indice + matriz)
.C and C++ handle arrays as a pointer to the first position of the array in memory, then accessed via the index to access each position.
That said, it turns out that the compiler converts this:
In this:
With normal syntax it would become
in this:
and therefore both expressions are equivalent and obtain the same value. This also applies to C.
As you may have read in other answers
E1[E2] == *((E1)+(E2))
But it's not always like this.
When an operator is overloaded, it obeys the syntax rules of the operator, but the operand type, value category, and evaluation order requirements are overridden by the rules of a function invocation, as noted in Note 2 to chapter 5 of the standard :
This is easy to check with the following program:
indice[arreglo]
is the syntactic sugar of*(indice+arreglo)
, knowing that and since it(x + y)
is commutative you could also do it like this*(arreglo+indice)
and get the same result.Shell:
Since the topic was revived, I take the opportunity to say that I think the explanations that clarify the reason for
array[indice] == indice[array]
, when that is true, are very good; Well, I agree with almost all the answers.But it would be necessary to add that this equality is always valid in C but not always in C++; in fact many times the expression
indice[array]
doesn't make sense, it's not a valid expression (and fortunately it doesn't compile either).The difference is that in C++ the expression
E1[E2] == *((E1)+(E2))
has an additional condition:C++ Standard [8.2.1 Subscripting]
In expressions compatible with C there is no problem, because one of these
E
expressions is always a pointer toT
(or decays into a pointer to T), but it is not necessarily always so.Example. Here, overloading the [] operator gives meaning to
terna[indice]
, but it is not possible to doindice[terna]
: