VC++ 6.0 vs. GCC Unterschiedliche Behandlung von postfixer Inkrementierung



  • In wiefern undefiniert?



  • Es ist nicht durch den Standard festgelegt, ob der Seiteneffekt des Postinkrement vor oder nach der Zuweisung eintritt. Der Compiler darf da machen, was er will.



  • Achso okay

    Gibt es denn dafür eine bestimmten Grund, dass der Compiler machen kann, was er will, oder wurde es als nicht grundlegend erachtet?



  • Knacks schrieb:

    Gibt es denn dafür eine bestimmten Grund, dass der Compiler machen kann, was er will, oder wurde es als nicht grundlegend erachtet?

    Naja, Ansich kann der Compiler nicht machen was er will: j++ gibt den alten Wert zurück.

    Aber: Es ist nicht definiert wann genau der Seiteneffekt auftritt. Da du hier eine Selbstzuweisung machst, kann es entscheiden sein ob das Inkrement nach der eigentlichen Zuweisung oder davor passiert.

    Ich ändere deinen Code mal leicht ab:

    #include <iostream>
    
    int main()
    {  
      int j = 0;
      for (int i=0; i<100; ++i)
      {
        int temp = j++;
        j = temp;
      }
      std::cout << j << std::endl;
      std::cin.get();
    }
    

    Dieser Code ergibt auch unter VC als Endergebnis 0. Also wo liegt der Unterschied?

    Betrachten wir nochmal folgendes:

    // Zuweisung bei dir
    j = j++;
    // Zuweisung bei mir
    int temp = j++;
    j = temp;
    

    Der erste Fall kann wie folgt aufgelöst werden:

    a) Seiteneffekt vor Zuweisung (GCC)
    1. Rückgabe des alten Wertes => Tempvariable
    2. [Seiteneffekt] Inkrement von j
    3. Zuweisung der Tempvariable zu j

    b) Seiteneffekt nach Zuweisung (VC)
    1. Rückgabe des alten Wertes => Tempvariable
    2. Zuweisung der Tempvariable zu j
    3. [Seiteneffekt] Inkrement von j

    Der von mir eingeführte Zwischenschritt führt nicht zu diesem Seiteneffekt da ich den alten Wert nicht j zuweise, sondern erst nach Abarbeitung der Seiteneffekte eine Zuweisung mache.



  • Das heisst in Zukunft bei einer Inkrementierung, bei der es wichtig ist, wann inkrementiert wird, lieber mit einer Zwischenvariablen arbeiten, so dass dadurch sicher gestellt ist, das dieser Seiteneffeckt nicht auftritt.

    Danke für eure schnelle Hilfe.

    Gibt es auch noch andere Situationen, wo der Standard dazu nichts genau definiert? (Also relativ leichte Sachen, nichts sehr sehr kompliziertes):



  • Bemühe vielleicht auch mal eine Suchmschine Deiner Wahl nach "Sequence Points". Da solltest Du fündig werden.



  • Knacks schrieb:

    Das heisst in Zukunft bei einer Inkrementierung, bei der es wichtig ist, wann inkrementiert wird, lieber mit einer Zwischenvariablen arbeiten, so dass dadurch sicher gestellt ist, das dieser Seiteneffeckt nicht auftritt.

    Eher darauf achten, dass Du im selben Ausdruck, in dem die Inkrementierung stattfindet, nicht die Inkrementierte Variable benutzt. Welchen Sinn soll der Ausdruck "inkrementiere j, aber weise j den alten Inhalt von j zu" denn haben?



  • LordJaxom schrieb:

    [...]
    Welchen Sinn soll der Ausdruck "inkrementiere j, aber weise j den alten Inhalt von j zu" denn haben?

    j=j++ hatte ich ja gerade so verstanden, das "inkrementiere j und weise j den neuen wert zu" ausgeführt wird.

    Oder wie meinst du das?



  • Knacks schrieb:

    j=j++ hatte ich ja gerade so verstanden, das "inkrementiere j und weise j den neuen wert zu" ausgeführt wird.

    j++ ist aber "inkrementiere j und gebe den alten Wert zurück".

    Aber die Frage zielte eigentlich eher auf "welchen Sinn macht 'Zuerst ändere j (indem es um eins hochgezählt wird) und danach ändere j (durch Zuweisung des hochgezählten Wertes)'?"

    Oder, da Du ein Verständnisproblem mit dem Inkrementierungsoperator zu haben scheinst, welchen Sinn würde folgendes machen:

    j = (j = j + 1)
    


  • Knacks schrieb:

    j=j++ hatte ich ja gerade so verstanden, das "inkrementiere j und weise j den neuen wert zu" ausgeführt wird.

    Das wäre beim Postkrement sicher eine falsche Interpretation. j++ gibt den alten Wert zurück (über eine temporäre Variable), ++j den neuen (ohne Umweg über eine temporäre Variable). Eine Zuweisung ist auch nicht nötig, da beide den Wert von j ändern.

    cu André



  • LordJaxom schrieb:

    Oder, da Du ein Verständnisproblem mit dem Inkrementierungsoperator zu haben scheinst, welchen Sinn würde folgendes machen:

    j = (j = j + 1)
    

    Ich weiss, dass das keinen Sinn macht, war gerade auf nem falschen Gedankengang und bin dadurch etwas durcheinander (2 verschiedene Dinge auf einmal bedenken ist doch net ganz so leicht)

    Ich weiss auch, dass Programm insgesamt wenig Sinn macht und ich bin durch Zufall beim rum experimentieren darauf gekommen.

    Was mich aber halt irritiert hat,war das beim VC++ j ja gerade nicht den alten Wert zurückgewiesen bekommen hat, sondern fleissig hochgezählt hat.
    Und das hatte MFK ja bereits beantwortet


Anmelden zum Antworten