1818 Stimmen

Warum ist es bei Arrays so, dass a[5] == 5[a]?

Wie Joel unterstreicht in Stack Overflow-Podcast #34 , in Programmiersprache C (auch bekannt als: K & R), wird diese Eigenschaft von Arrays in C erwähnt: a[5] == 5[a]

Joel sagt, dass es an der Zeigerarithmetik liegt, aber ich verstehe es immer noch nicht. Warum ist a[5] == 5[a] ?

14voto

A.s. Bhullar Punkte 2510

Sie enthält sehr gute Erklärungen in EIN TUTORIAL ZU ZEIGERN UND ARRAYS IN C von Ted Jensen.

Ted Jensen erklärte dies wie folgt:

In der Tat ist dies richtig, d.h. wo immer man schreibt a[i] kann es sein ersetzt werden durch *(a + i) ohne jegliche Probleme. Tatsächlich wird der Compiler in beiden Fällen den gleichen Code erzeugen. Wir sehen also, dass Zeiger Arithmetik dasselbe ist wie die Indizierung von Arrays. Jede der beiden Syntaxen erzeugt das gleiche Ergebnis.

Dies bedeutet NICHT, dass Zeiger und Arrays das Gleiche sind, das sind sie nicht. Wir sagen nur, dass wir zur Identifizierung ein bestimmtes Element eines Arrays zu identifizieren, haben wir die Wahl zwischen zwei Syntaxen, eine eine mit Array-Indizierung und die andere mit Zeigerarithmetik, die identische Ergebnisse liefern.

Nun, wenn man sich diese letzte Ausdruck, ein Teil davon (a + i) ist eine einfache Addition unter Verwendung des + Operator, und die Regeln von C besagen, dass ein solcher Ausdruck kommutativ ist. Das heißt, (a + i) ist identisch mit (i + a) . Wir könnten also schreiben. *(i + a) genauso leicht wie *(a + i) . Aber *(i + a) könnte stammen aus i[a] ! Aus all dem ergibt sich die merkwürdige Wahrheit, dass wenn:

char a[20];

Schreiben

a[3] = 'x';

ist dasselbe wie das Schreiben

3[a] = 'x';

11voto

Ajinkya Patil Punkte 721

Ich weiß, dass die Frage beantwortet ist, aber ich konnte nicht widerstehen, diese Erklärung mitzuteilen.

Ich erinnere mich an Principles of Compiler design, Nehmen wir an a ist eine int Array und Größe der int beträgt 2 Bytes, & Basisadresse für a ist 1000.

Wie a[5] wird funktionieren ->

Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010

Así que,

Ähnlich verhält es sich, wenn der c-Code in 3-Adressen-Code zerlegt wird, 5[a] wird ->

Base Address of your Array a + (size of(data type for array a)*5)
i.e. 1000 + (2*5) = 1010 

Im Grunde genommen verweisen also beide Anweisungen auf denselben Speicherplatz und damit auf die gleiche Stelle, a[5] = 5[a] .

Diese Erklärung ist auch der Grund, warum negative Indizes in Arrays in C funktionieren.

d.h. wenn ich auf a[-5] wird es mir

Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990

Sie gibt mir das Objekt an der Position 990 zurück.

10voto

dgnuff Punkte 2771

Nun ein wenig Geschichte. Neben anderen Sprachen hatte BCPL einen ziemlich großen Einfluss auf die frühe Entwicklung von C. Wenn Sie ein Array in BCPL mit etwas wie:

let V = vec 10

die tatsächlich 11 Wörter Speicher zugewiesen hat, nicht 10. Typischerweise war V das erste und enthielt die Adresse des unmittelbar folgenden Wortes. Im Gegensatz zu C ging also die Benennung von V an diese Stelle und nahm die Adresse des nullten Elements des Arrays auf. Daher ist die Array-Indirektion in BCPL, ausgedrückt als

let J = V!5

wirklich zu tun hatte J = !(V + 5) (unter Verwendung der BCPL-Syntax), da es notwendig war, V zu holen, um die Basisadresse des Arrays zu erhalten. Daher V!5 y 5!V gleichbedeutend waren. Als anekdotische Beobachtung wurde WAFL (Warwick Functional Language) in BCPL geschrieben, und soweit ich mich erinnere, wurde für den Zugriff auf die als Datenspeicher verwendeten Knoten eher die letztere als die erstere Syntax verwendet. Zugegeben, das ist irgendwo zwischen 35 und 40 Jahren her, mein Gedächtnis ist also etwas eingerostet :)

Die Innovation, auf das zusätzliche Speicherwort zu verzichten und den Compiler die Basisadresse des Arrays beim Benennen einfügen zu lassen, kam erst später. Laut dem C History Paper geschah dies etwa zu der Zeit, als Strukturen zu C hinzugefügt wurden.

Beachten Sie, dass ! war in BCPL sowohl ein unärer Präfix-Operator als auch ein binärer Infix-Operator, der in beiden Fällen eine Indirektion durchführte, wobei die binäre Form eine Addition der beiden Operanden vor der Indirektion beinhaltete. In Anbetracht des wortorientierten Charakters von BCPL (und B) war dies tatsächlich sehr sinnvoll. Die Einschränkung "Zeiger und Ganzzahl" wurde in C notwendig, als es Datentypen gab, und sizeof wurde zu einer Sache.

8voto

Krishan Punkte 277

In C-Arrays, arr[3] y 3[arr] sind gleich, und ihre entsprechenden Zeigernotationen sind *(arr + 3) a *(3 + arr) . Aber im Gegenteil [arr]3 o [3]arr ist nicht korrekt und führt zu einem Syntaxfehler, da (arr + 3)* y (3 + arr)* sind keine gültigen Ausdrücke. Der Grund dafür ist, dass der Dereferenzierungsoperator vor der Adresse platziert werden sollte, die der Ausdruck liefert, nicht nach der Adresse.

8voto

AVIK DUTTA Punkte 724

In C-Compiler

a[i]
i[a]
*(a+i)

sind verschiedene Möglichkeiten, sich auf ein Element in einem Array zu beziehen ! (GANZ UND GAR NICHT SELTSAM)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X