In C ist es möglich, die Operanden der Array-Subskribierung umzukehren und trotzdem das gleiche Ergebnis zu erzielen. Zum Beispiel a[b] == b[a]
. Dies ist, weil (gemäß C11 Entwurf N1570, §6.5.2.1 / 2 ) a[b]
ist identisch mit (*((a)+(b)))
und +
ist kommutativ. Weitere Informationen finden Sie unter diese Frage .
Gibt es jemals ein Szenario (in C, wo kein Operator überladen ist), bei dem die Operanden des []
Operators nicht zur Laufzeit denselben Wert ergeben? Gibt es also a
und b
für welche a[b] != b[a]
? (Angenommen das Programm kompiliert und a[b] == a[b]
)
Sie scheinen Ihre eigene Frage meistens mit Ihrer Wiederholung beantwortet zu haben, warum a[b]
dasselbe bedeutet wie b[a]
. Diese Erklärung ist richtig und gründet direkt auf dem Standard. Der Hauptvorbehalt ist, dass a
und b
Typen und Werte haben müssen, so dass die Bewertung von a[b]
überhaupt ein definiertes Verhalten hat. Solange dies der Fall ist, müssen die beiden Ausdrücke dasselbe bewerten. Sonst hat C nichts darüber zu sagen, ob die beiden Ausdrücke dasselbe ausdrücken.
Wenn a
und b
Ausdrücke komplizierter darstellen als Variablennamen und Konstanten, dann ist es möglich, sie so zu wählen, dass overall bedingter Ausdruck (a)[b] == (b)[a]
hat ein undefiniertes Verhalten, obwohl die Auswertung der linken und rechten Sub-Ausdrücke individuell ein definiertes Verhalten hat. Zum Beispiel
Insgesamt gibt es jedoch keinen Fall, in dem C den Ausdruck (a)[b] != (b)[a]
als wahr definiert, unabhängig von Typ, Form oder Werten von a
und b
.
Nun, wenn Sie das als ein gültiges Gegenbeispiel betrachten:
%Vor% Der Grund dafür ist, dass der tiefgestellte Operator eine höhere Priorität als der Indirektionsoperator hat, also *i[i]
entspricht *(i[i])
, was ungültig ist, weil der Subscript-Operator nicht zwei Zeigertypen annehmen kann.
Beachten Sie, dass diese Beispiele natürlich ein undefiniertes Verhalten ergeben, wenn sie tatsächlich ausgeführt werden. Es soll nur die Frage des OP beantworten.
Betrachten Sie das folgende Programm:
%Vor%Die Ausgabe ist:
%Vor%
Wie diese Antwort , nutzt es die Tatsache, dass []
eine höhere Priorität hat als unary *
. Also:
a[b]
& amp; rightarrow; (*y)[*z]
& amp; rightarrow; (1)[x[0]]
≡ x[0][1]
& ist gleich; %Code%
2
& amp; rightarrow; b[a]
& amp; rightarrow; *z[(*y)]
≡ *x[(1)]
& ist gleich; %Code%
Während ich beiläufig die WebKit-Quelle überflog, fand ich ein Beispiel , in dem der Autor die Operanden absichtlich in einen Array-Zugriff umgewandelt hat.
%Vor% Beachten Sie, dass der Autor an zwei Stellen 0[x]
anstelle des traditionelleren x[0]
verwendet. Der Grund dafür liegt vermutlich darin, dass diese Verwendung innerhalb eines Makros und nicht im Rohcode erfolgt. Da x
tatsächlich ein Parameter für das Makro ist, wird sein Wert textuell in den Makro-Hauptteil eingefügt. Eine Konsequenz daraus ist, dass x
nicht ein einzelner Bezeichner sein muss, sondern vielleicht im Infix-Ausdruck. In diesem Fall besteht die Möglichkeit, dass Probleme mit der Operatorpräzedenz auftreten. Nehmen Sie zum Beispiel diese Verwendung:
Wenn die Operanden umgekehrt wurden, würden die beiden Aufrufe von ARRAY_SIZE
auf a[0]
bzw. b+1[0]
erweitert. Ersteres funktioniert wie vorgesehen, aber Letzteres ist wahrscheinlich ein Segmentierungsfehler, da es b+(1[0])
entspricht.
Effektiv hat der Autor durch Umkehrung der Operanden in den Array-Zugriff die Notwendigkeit vermieden, proaktiv ihre Makroparameter in Klammern zu setzen. Dies ist möglicherweise keine unglaublich mächtige Verwendung, aber es ist ein kleiner Vorteil, Operanden umzukehren, bei der (wahrscheinlich viel größeren) Kosten der Lesbarkeit.
in int *i;
*i[i]; // like number[pointer]
i[*i]; // does like pointer[number]
und pointer[number]
ist die Art, wie Sie zu einem Mitglied in einem Array gehen.
auch die i[*i]
wird nicht kompiliert, wenn Sie int *i;
nicht zu int *i; *i=value;
wenn value eine Zahl ist.