Was ist ‘-1[p]’ wenn p auf ein Array (von int) index zeigt? [duplicate]

Lesezeit: 5 Minuten

Benutzer-Avatar
Erik Stroeken

Heute bin ich über ein C-Rätsel gestolpert, das eine neue Überraschung für mich bereithält.

Ich dachte nicht, dass -1[p] im folgenden Beispiel würde kompilieren, aber es tat. Tatsächlich ist x am Ende -3.

    int x;
    int array[] = {1, 2, 3};
    int *p = &array[1];
    x = -1[p]

Ich suchte im Internet nach so etwas wie -1[pointer] konnte aber nichts finden. Okay, es ist schwierig, die richtige Suchanfrage einzugeben, gebe ich zu. Wer weiß warum -1[p] kompiliert und X wird zu -3?

  • Es ist dasselbe wie -(p[1]) was dasselbe ist wie -(array[2]).

    – Eugen Sch.

    14. August 2019 um 17:22 Uhr

  • Das Rätsel hat zwei Ebenen: Um es zu verstehen, muss man das zuerst wissen a[5] == 5[a]. Aber wenn Sie sich nicht auch die weniger intuitiven Vorrangregeln von C gemerkt haben oder wenn Sie sich nicht daran erinnern, dass C behandelt -1 Als Anwendung des unären Minusoperators (anstatt ihn als ein einzelnes Token und eine an sich negative Konstante zu behandeln), könnten Sie sich täuschen lassen, dies zu denken -1[p] ist das gleiche wie p[-1] statt -(p[1]).

    – zol

    14. August 2019 um 17:42 Uhr


  • Und natürlich bindet es niedriger als Indexierung, weil es sonst vernünftig aussieht -p[1] würde versuchen, einen Zeiger zu negieren …

    – Antti Haapala – Слава Україні

    14. August 2019 um 17:50 Uhr

  • @EugenSch. Ich wollte gerade für die stimmen a[5] == 5[a] auch eins als dup, aber es deckt wirklich nur die Hälfte dieser Frage ab. Ich würde sagen, dass der überraschende Vorrang hier ebenso bedeutsam ist.

    – Steve Summit

    14. August 2019 um 18:23 Uhr


  • @SteveSummit Ich bin mir nicht sicher, warum der Vorrang so überraschend ist und eine ganze Frage mit 5 Antworten verdient. Ja, es kann ein bisschen verwirrend sein, aber es ist eine sehr grundlegende Sache, insbesondere angesichts der Ergebnisse der Codeausführung.

    – Eugen Sch.

    14. August 2019 um 18:30 Uhr


Ich bin die Person, die dieses “Rätsel” gemacht hat (siehe mein Twitter-Post)

So! Was ist mit -1[p]?

ISO C definiert tatsächlich [] symmetrisch sein, d.h x[y] ist das gleiche wie y[x]wobei x und y beide Ausdrücke sind.

Naiverweise könnten wir zu dem Schluss kommen, dass -1[p] ist deshalb p[-1] und so x = 1-1 ist jedoch tatsächlich der unäre Minusoperator, der auf die Konstante 1 angewendet wird, und unäres Minus hat eine niedrigere Priorität als []

So, -1[p] ist -(p[1])was -3 ergibt.

Dies kann auch zu funky aussehenden Snippets wie diesem führen:

sizeof(char)["abc"] /* yields 'b' */

Das erste, was herauszufinden ist, ist der Vorrang. Nämlich [] hat eine höhere Priorität als unäre Operatoren, also -1[p] ist gleich -(1[p])nicht (-1)[p]. Also nehmen wir das Ergebnis von 1[p] und negiert es.

x[y] ist gleich *(x+y)Also 1[p] ist gleich *(1+p)was gleich ist *(p+1)was gleich ist p[1].

Also nehmen wir das Element eins nach wo p Punkte, also das dritte Element von arraydh 3, und dann negieren, was uns gibt -3.

Benutzer-Avatar
Vlad aus Moskau

Gemäß dem C-Standard (6.5.2 Postfix-Operatoren) ist der Subscript-Operator wie folgt definiert

postfix-expression [ expression ]

Vor den eckigen Klammern soll also ein Postfix-Ausdruck stehen.

In dieser Ausdrucksanweisung

x = -1[p];

Es wird der Postfix-Ausdruck verwendet 1 (das ist gleichzeitig ein primärer Ausdruck), der Postfix-Ausdruck 1[p] (das ist der tiefgestellte Operator) und der unäre Operator - Berücksichtigen Sie, dass, wenn der Compiler ein Programm in Token aufteilt, ganzzahlige Konstanten ohne das Minus selbst als Token betrachtet werden. minus ist ein separates Token.

So kann die Aussage wie umgeschrieben werden

x = -( 1[p] );

weil ein Postfix-Ausdruck eine höhere Priorität hat als ein unärer Ausdruck.

Betrachten wir zunächst den Postfix-Unterausdruck 1[p]

Gemäß dem C-Standard (6.5.2.1 Array-Subskription)

2 Ein Postfix-Ausdruck gefolgt von einem Ausdruck in eckigen Klammern []
ist eine tiefgestellte Bezeichnung eines Elements eines Array-Objekts. Die Definition des Indexoperators [] ist das E1[E2] ist identisch mit (*((E1)+(E2))). Aufgrund der Konvertierungsregeln, die für den binären +-Operator gelten, ist E1 E1, wenn E1 ein Array-Objekt (äquivalent ein Zeiger auf das Anfangselement eines Array-Objekts) und E2 eine ganze Zahl ist[E2] bezeichnet das E2-te Element von E1 (gezählt von Null).

Dieser Unterausdruck wird also wie ausgewertet *( ( 1 ) + ( p ) ) und ist dasselbe wie *( ( p ) + ( 1 ) ).

Daher obige Aussage

x = -1[p];

ist äquivalent zu

x = -p[1];

und wird nachgeben -3weil der Zeiger p zeigt aufgrund der Anweisung auf das zweite Element des Arrays

int *p = &array[1];

und dann der Ausdruck p[1] liefert den Wert des Elements nach dem zweiten Element des Arrays. Dann der unäre Operator - wird angewandt.

Benutzer-Avatar
Achal

Dies

int array[] = {1, 2, 3};

sieht aus wie

array[0]   array[1]  array[2]
 --------------------------
|     1   |    2    |   3  | 
 --------------------------
 0x100     0x104     0x108   <-- lets assume 0x100 is base address of array
array

Als nächstes, wenn Sie möchten

int *p = &array[1];

der Integer-Zeiger p zeigt auf Adresse von array[1] dh 0x104. Es sieht aus wie

array[0]   array[1]  array[2]
 --------------------------
|     1   |    2    |   3  | 
 --------------------------
 0x100     0x104     0x108   <-- lets assume 0x100 is base address of array
             |
            p holds 0x104

Und wenn es Ihnen gefällt

x = -1[p]

-1[p] ist äquivalent zu -(1[p]) dh -(p[1]). es sieht aus wie

-(p[1]) ==> -(*(p + 1*4)) /* p holds points to array[1] i.e 0x104 */
        ==> -(*(0x104 + 4))
        ==> -(*(0x108)) ==> value at 0x108 is 3
        ==> prints -3

Benutzer-Avatar
Jordan Motta

Was hier passiert, ist wirklich interessant.

p[n] meint *(p+n). Deshalb sehen Sie 3, weil “p” auf ein Array zeigt[1] was 2 ist, und -p[1] wird interpretiert als -(*(p+1)) das ist -3.

1286790cookie-checkWas ist ‘-1[p]’ wenn p auf ein Array (von int) index zeigt? [duplicate]

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

Privacy policy