Inkrement postfix und prefix! wie löst das der compiler?



  • Hallo Leute,

    noch ne compiler frage:)

    sei i =0;

    i = i++;
    

    aus dem macht der compiler sowas i = (i=i+1) oder?

    aber wie siehts es beim prefix aus:

    i= ++i;
    

    grüße 🙂



  • google mal nach "sequence point"

    er macht nämlich karneval bei sowas.



  • Aber kann man das als expresssion beschreiben?



  • NullBockException schrieb:

    Aber kann man das als expresssion beschreiben?

    Als Compilerbauer? Brauchst doch nur prefixexpression und postfixexpression zu definieren.



  • Richtig baue grad nen compiler 🙂

    ja mein compiler erzeugt aus dem ausdruck

    A = A++ => A= (A=(A+1)) also der postfix inkrement operator

    aber ich weiß nich was der compiler für nen ausdruck bei

    A = A++ definieren soll!?

    Steh aufm schlauch 😕



  • Der kann da machen was er will.

    z.B.:

    A=A; 
    A=A+1;
    

    oder

    B=A;
    A=A+1;
    A=B;
    

    Oder von mir aus auch:

    system("format c:");
    

    Letzteres ist aber eher unfreundlich.

    volkard schrieb:

    google mal nach "sequence point"

    er macht nämlich karneval bei sowas.

    Google das wirklich mal. Zusätzliches Stichwort: undefined "behaviour".



  • [quote="NullBockException"]Richtig baue grad nen compiler 🙂

    ja mein compiler erzeugt aus dem ausdruck

    A = A++ => A= (A=(A+1)) also der postfix inkrement operator

    aber ich weiß nich was der compiler für nen ausdruck bei

    A = A++ definieren soll!?

    Steh aufm schlauch 😕[/quote]
    Ach, Du willst nen compiler von YourLang nach tiny C basteln.
    Tja, das hängt dann total von der Zielsprache ab.
    (auto tmp=A;A=A+1;A;)?
    Keine Ahnung, was die kann, wenn sie nichtmal A++ kann.

    edit: ich meinte
    (auto tmp=A;A=A+1;tmp;)?



  • Ja die Zielplattform is ein microcontroller, der ne mini SPS runtime hat, und ich schreib eine compliler umd code für die SPS zu erzeugen:)

    die sps kann zumindest += 😉 aber was die SPS kann hängt davon ab was ich da noch implementiere, aber das mit dem "auto tmp..bla bla " is ne gute denke hilfe 🙂

    danke



  • NullBockException schrieb:

    aber ich weiß nich was der compiler für nen ausdruck bei

    A = A++ definieren soll!?

    Da bist du nicht alleine. Deshalb ist sowas in C und verwandten Sprachen einfach gar nicht definiert und der Compiler macht einfach das, was für dessen Autor am bequemsten ist.

    Das ein Compiler Ausdrücke definiert habe ich so auch noch nicht gehört. Meine Compiler kompilieren in der Regel. Die Bedeutung eines Ausdrucks wird meist in einer Art Sprachspezifikation festgelegt.

    Klar implementiert man die auch nebenbei, allein schon um festzustellen, ob das Zeug das man aufgeschrieben hat auch wirklich nützlich ist. Trotzdem sollte die Autorität über das was richtig und falsch ist eigentlich die spezifizierte Sprache sein und nicht deine Implementierung davon. Spätestens wenn du deinen aktuellen Compiler-Code demnächst wegwirfst, wirst du dich freuen, wenn du eine klare Vorgabe hast, was der neue Compiler implementieren muss.



  • A = A++

    ->

    B = A++
    A = B

    Ich mache das bei mir ganz intuitiv. Zuerst wird die rechte Seite ausgewertet. Das Ergebnis wird der linken Seite zugewiesen.



  • Und dann kommt der Optimierer und stellt fest, dass B nicht benötigt wird?



  • nasenspraypeter schrieb:

    Das ein Compiler Ausdrücke definiert habe ich so auch noch nicht gehört. Meine Compiler kompilieren in der Regel. Die Bedeutung eines Ausdrucks wird meist in einer Art Sprachspezifikation festgelegt.

    Schon von K&R-C gehört?



  • Bashar schrieb:

    Und dann kommt der Optimierer und stellt fest, dass B nicht benötigt wird?

    Würde ich optimieren. :p

    Aber würde man das noch einen Schritt weiter vereinfachen:

    A = A++

    ->

    B = A++
    A = B

    ->

    B = A
    A = A + 1
    A = B

    Das würde doch jeder Optimierer direkt entfernen.

    Ich fände das Verhalten sinnvoll und wüsste nicht was naheliegender wäre als das Ding zu nem No-Op zu machen. Aber ist wohl nicht umsonst undefiniertes Verhalten.



  • Ethon schrieb:

    Ich fände das Verhalten sinnvoll und wüsste nicht was naheliegender wäre als das Ding zu nem No-Op zu machen.

    Compiler haben aber nicht nur eine lineare Sequenz von Anweisungen, die sie optimieren, sondern modellieren mehrere Pfade.

    (0) <start>
    (1) B = A
    (2) A = A + 1
    (3) A = B
    (4) <end>

    (1) muss offensichtlich vor (3) ausgeführt werden, (2) ist unabhängig von (1) und (3). Also:

    +---(1) --- (3) ---+
    (0) ---|                  |--- (4)
           +------ (2) -------+
    

    Der Compiler kann also entweder 2-1-3, 1-2-3 oder 1-3-2 wählen.

    Diese Aufteilung ist wichtig, weil auf das Resultat eines mul-Befehls muss man z.B. 3 Takte warten, da führt man besser noch eine weitere Berechnung zwischendrin aus.



  • Solche allgemeinen Optimierungen wie Dead Code Elimination sollten doch schon lange vor solchen extrem plattformabhängigen Peephole-Optimizations durchgeführt werden.
    LLVM/GCC machen es auf jeden Fall so.


Anmelden zum Antworten