Grund für das Umkehren von Operanden in Array-Zugriff / Subskribierung

8

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] )

    
user12341234 18.02.2017, 19:30
quelle

5 Antworten

4

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

%Vor%

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 .

    
John Bollinger 18.02.2017 19:53
quelle
3

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.

    
Downvoter 18.02.2017 19:45
quelle
0

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%
jxh 18.02.2017 21:21
quelle
0

Ja - für Bedenken bezüglich der Operator-Priorität in einem Makro-Körper

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:

%Vor%

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.

    
user12341234 31.12.2017 21:27
quelle
-1

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;

ändern

wenn value eine Zahl ist.

    
רועי אבידן 18.02.2017 20:56
quelle

Tags und Links