Ich glaube, dass die anderen Antworten etwas übersehen haben.
Ja, p[i]
ist per Definition äquivalent zu *(p+i)
, was (da die Addition kommutativ ist) äquivalent ist zu *(i+p)
, die (wiederum durch die Definition des []
Operator) ist äquivalent zu i[p]
.
(Und in array[i]
wird der Array-Name implizit in einen Zeiger auf das erste Element des Arrays umgewandelt).
Aber die Kommutativität der Addition ist in diesem Fall nicht ganz so offensichtlich.
Wenn beide Operanden vom gleichen Typ sind, oder sogar von verschiedenen numerischen Typen, die zu einem gemeinsamen Typ promotet werden, ist die Kommutativität absolut sinnvoll: x + y == y + x
.
In diesem Fall geht es aber speziell um Zeigerarithmetik, bei der ein Operand ein Zeiger und der andere eine ganze Zahl ist. (Ganzzahl + Ganzzahl ist eine andere Operation, und Zeiger + Zeiger ist Unsinn.)
Die im C-Standard enthaltene Beschreibung der +
Betreiber ( N1570 6.5.6) sagt:
Bei der Addition müssen entweder beide Operanden vom arithmetischen Typ sein, oder einer Operand ein Zeiger auf einen vollständigen Objekttyp und der andere muss vom Typ Ganzzahl sein.
Es hätte genauso gut heißen können:
Bei der Addition müssen entweder beide Operanden vom arithmetischen Typ sein, oder die Linke Operand muss ein Zeiger auf einen vollständigen Objekttyp sein und der rechter Operand muss vom Typ Ganzzahl sein.
in diesem Fall sowohl i + p
y i[p]
wäre illegal.
In C++ haben wir eigentlich zwei Sätze von überladenen +
Operatoren, die sich grob wie folgt beschreiben lassen:
pointer operator+(pointer p, integer i);
y
pointer operator+(integer i, pointer p);
von denen nur der erste wirklich notwendig ist.
Warum also ist das so?
C++ hat diese Definition von C geerbt, das sie von B übernommen hat (die Kommutativität der Array-Indizierung wird ausdrücklich in der 1972 Verweis der Nutzer auf B ), die es von BCPL (Handbuch aus dem Jahr 1967), das möglicherweise aus noch früheren Sprachen (CPL? Algol?) stammt.
Die Idee, dass die Indizierung von Arrays durch Addition definiert ist und dass die Addition, selbst von Zeigern und ganzen Zahlen, kommutativ ist, geht also viele Jahrzehnte zurück, bis zu den Vorgängersprachen von C.
Diese Sprachen waren viel weniger stark typisiert als das moderne C. Insbesondere die Unterscheidung zwischen Zeigern und ganzen Zahlen wurde oft ignoriert. (Frühe C-Programmierer verwendeten Zeiger manchmal als ganze Zahlen ohne Vorzeichen, bevor die unsigned
Schlüsselwort wurde der Sprache hinzugefügt). Auf die Idee, die Addition nicht kommutativ zu machen, weil die Operanden von unterschiedlichem Typ sind, wären die Entwickler dieser Sprachen also wahrscheinlich nicht gekommen. Wenn ein Benutzer zwei "Dinge" addieren wollte, ganz gleich, ob es sich bei diesen "Dingen" um ganze Zahlen, Zeiger oder etwas anderes handelte, lag es nicht an der Sprache, dies zu verhindern.
Und im Laufe der Jahre hätte jede Änderung dieser Regel zu einem Bruch des bestehenden Codes geführt (obwohl der ANSI C-Standard von 1989 eine gute Gelegenheit gewesen sein könnte).
Wenn man C und/oder C++ dahingehend ändert, dass der Zeiger links und die ganze Zahl rechts stehen muss, könnte das zwar zu einem Bruch im bestehenden Code führen, aber es gäbe keinen Verlust an echter Ausdruckskraft.
Wir haben jetzt also arr[3]
y 3[arr]
bedeutet genau dasselbe, obwohl die letztere Form niemals außerhalb der IOCCC .