Sind negative Array-Indizes in C erlaubt?

Lesezeit: 6 Minuten

Benutzeravatar von bodacydo
bodacydo

Ich habe gerade einen Code gelesen und festgestellt, dass die Person ihn verwendet arr[-2] um auf das 2. Element vor dem zuzugreifen arrso:

|a|b|c|d|e|f|g|
       ^------------ arr[0]
         ^---------- arr[1]
   ^---------------- arr[-2]

Ist das erlaubt?

ich weiß das arr[x] ist das gleiche wie *(arr + x). So arr[-2] ist *(arr - 2), was in Ordnung zu sein scheint. Was denkst du?

Das ist richtig. Aus C99 §6.5.2.1/2:

Die Definition des Indexoperators [] ist das E1[E2] ist identisch mit (*((E1)+(E2))).

Es gibt keine Magie. Es ist eine 1-1 Äquivalenz. Wie immer beim Dereferenzieren eines Zeigers

  • müssen Sie sicher sein, dass es auf eine gültige Adresse verweist. somearray-2 Beachten Sie auch, dass Sie den Zeiger nicht dereferenzieren müssen, um UB zu erhalten. Reines Rechnen somearray ist undefiniert, es sei denn, das Ergebnis liegt im Bereich von Beginn an

    bis 1 nach seinem Ende.

    – RBerteig

  • 13. August 2010 um 9:12 Uhr [] In älteren Büchern die wurden als bezeichnet Syntax Zucker für Zeigerarithmetik. Favorit 1[arr] Ein Weg, Anfänger zu verwirren, ist zu schreiben arr[1] – Anstatt von

    – und beobachten Sie, wie sie raten, was das bedeuten soll.

    – Dummy00001

  • 13. August 2010 um 14:24 Uhr

    Was passiert auf 64-Bit-Systemen (LP64), wenn Sie einen negativen 32-Bit-Int-Index haben? Soll der Index vor der Adressberechnung zu einem 64-Bit-Signed-Int hochgestuft werden?

    – PaulR

  • 11. Oktober 2010 um 16:02 Uhr ((E1)+(E2)) @Paul aus §6.5.6/8 (Additive Operatoren): „Wenn ein Ausdruck vom Typ Integer zu einem Zeiger addiert oder von ihm subtrahiert wird, hat das Ergebnis den Typ des Zeigeroperanden. Wenn der Zeigeroperand auf ein Element zeigt eines Array-Objekts und das Array groß genug ist, zeigt das Ergebnis auf ein Element, das so vom ursprünglichen Element versetzt ist, dass die Differenz der Indizes der resultierenden und ursprünglichen Array-Elemente gleich dem ganzzahligen Ausdruck ist.” Also denke ich, dass es gefördert wird, und

    wird ein (64-Bit) Zeiger mit dem erwarteten Wert sein.

    – Matthäus Flaschen

  • 11. Oktober 2010 um 22:23 Uhr [] Eine kuriose Randbemerkung: Da der Index-Operator[E2] ist so definiert, dass E1 2[arr] identisch ist mit (*((E1)+(E2))) (siehe die Antwort von Matthew Flaschen), es ist tatsächlich gültiger C-Code zum Schreiben arr[2]Anstatt von

    . Ich gebe jedoch zu, dass dies den Code absichtlich verschleiert.

    – Christian Borgelt


19. Februar 2013 um 17:36 Uhr arr Dies gilt nur, wenn

int arr[10];

int x = arr[-2]; // invalid; out of range

ist ein Zeiger, der auf das zweite Element in einem Array oder ein späteres Element zeigt. Andernfalls ist es nicht gültig, da Sie auf Speicher außerhalb der Grenzen des Arrays zugreifen würden. Also falsch wäre zum Beispiel:

int arr[10];
int* p = &arr[2];

int x = p[-2]; // valid:  accesses arr[0]

Aber das wäre okay:

  • Es ist jedoch ungewöhnlich, einen negativen Index zu verwenden.

    @Matt: Der Code im ersten Beispiel ergibt undefiniertes Verhalten.

    – James McNellis

  • 13. August 2010 um 3:40 Uhr int arr[10]; Es ist ungültig. Nach dem C-Standard hat es explizit undefiniertes Verhalten. Andererseits, wenn arr[-2] waren Teil einer Struktur mit anderen Elementen davor, offsetofkönnte möglicherweise gut definiert sein, und Sie könnten feststellen, ob es darauf basiert

    etc.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

  • 13. August 2010 um 6:35 Uhr If one is sure that the elements exist, it is also possible to index backwards in an array; p[-1], p[-2], and so on are syntactically legal, and refer to the elements that immediately precede p[0]. Of course, it is illegal to refer to objects that are not within the array bounds. Gefunden in K&R Abschnitt 5.3, gegen Ende:

    Trotzdem hilft mir Ihr Beispiel besser, es zu verstehen. Vielen Dank!

    – Qiang Xu

  • 9. Mai 2012 um 20:47 Uhr

    Entschuldigung für die Nekromantie, aber ich finde es einfach toll, dass K&R nicht eindeutig ist, was “illegal” bedeutet. Der letzte Satz lässt es so klingen, als ob Zugriffe außerhalb der Grenzen einen Kompilierungsfehler auslösen. Das Buch ist Gift für Anfänger.

    – Martin

  • 14. Februar 2017 um 21:02 Uhr

    @Martin Um fair zu sein, wurde das Buch zu einem früheren Zeitpunkt in der Geschichte unserer Branche geschrieben, als es noch sehr vernünftig war, zu erwarten, dass “illegal” als “tu dies nicht, du darfst nicht” und nicht als “du wirst es sein” interpretiert wird daran gehindert“.

    – mtraceur

30. Dezember 2019 um 8:30 Uhr

  • Klingt gut für mich. Es wäre jedoch ein seltener Fall, dass Sie es rechtmäßig benötigen würden. Es ist nicht das

    selten – sehr nützlich zB bei der Bildverarbeitung mit Nachbarschaftsoperatoren.

    – PaulR


  • 11. Oktober 2010 um 15:56 Uhr [ structure / design ] Ich musste dies nur verwenden, weil ich einen Speicherpool mit einem Stapel und einem Haufen erstelle

    . Der Stack wächst zu höheren Speicheradressen, der Heap wächst zu niedrigeren Speicheradressen. Treffen in der Mitte.

    – KANJICODER

24. Januar 2020 um 16:12 Uhr arr Was war das wohl arr[-2] zeigte auf die Mitte des Arrays und machte daher

auf etwas im ursprünglichen Array zeigen, ohne die Grenzen zu überschreiten. Ich bin mir nicht sicher, wie zuverlässig das ist, aber ich habe gerade die folgende Einschränkung zu negativen Array-Indizes auf 64-Bit-Systemen (LP64 vermutlich) gelesen:

http://www.devx.com/tips/Tip/41349

  • Der Autor scheint zu sagen, dass 32-Bit-Int-Array-Indizes mit 64-Bit-Adressierung zu schlechten Adressberechnungen führen können, es sei denn, der Array-Index wird explizit auf 64 Bit hochgestuft (z. B. über einen ptrdiff_t-Cast). Ich habe tatsächlich einen Fehler dieser Art mit der PowerPC-Version von gcc 4.1.0 gesehen, aber ich weiß nicht, ob es sich um einen Compiler-Fehler handelt (dh sollte gemäß C99-Standard funktionieren) oder um ein korrektes Verhalten (dh Index muss auf 64 umgewandelt werden Bits für korrektes Verhalten) ?

    Das hört sich nach einem Compiler-Bug an.

    – Tischler

13. September 2013 um 15:46 Uhr
Benutzeravatar von Adrian Mole

Adrian Mol

Ich weiß, dass die Frage beantwortet ist, aber ich konnte nicht widerstehen, diese Erklärung zu teilen. a Ich erinnere mich an Prinzipien des Compiler-Designs: Nehmen wir an int ist ein int Array und Größe von 2ist a und die Basisadresse für 1000ist

. a[5] Wie wird

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

Arbeit -> a[-5] Diese Erklärung ist auch der Grund, warum negative Indizes in Arrays in C funktionieren; dh wenn ich zugreife

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

es wird mir geben:

  • Es wird das Objekt an Position 990 zurückgeben. Durch diese Logik können wir also auf negative Indizes in Arrays in C zugreifen.

    Das hört sich nach einem Compiler-Bug an.

    – Tischler

13. September 2013 um 15:46 Uhr
Benutzeravatar von Maximilian Ast

Maximilian Ast

  1. Warum sollte jemand negative Indizes verwenden, ich habe sie in zwei Kontexten verwendet:[1][-1] Eine Tabelle mit kombinatorischen Zahlen haben, die Ihnen sagt, dass Sie kämmen

  2. = 0; Sie können Indizes immer überprüfen, bevor Sie auf die Tabelle zugreifen, aber auf diese Weise sieht der Code sauberer aus und wird schneller ausgeführt.

     while (x < a[i]) i--;
    

Zentinel am Anfang einer Tabelle setzen. Zum Beispiel möchten Sie etwas wie verwenden i aber das solltest du dann auch prüfen
ist positiv. a[-1] Lösung: Mach es so -DBLE_MAXist x&lt;a[-1] so dass

1424270cookie-checkSind negative Array-Indizes in C erlaubt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy