Prä- und Postfix falsch??



  • Hallo liebe Gemeinde.

    Ich hätte einmal eine Frage zu Prä- und Postfix.

    Hier ersteinmal folgender Code (ich habe den Code programmiert, per Copy und Paste hier eingefügt, markiert und auf C/C++ unter dem Posting geklickt, also falls der Code nicht in Farbe ist, dann kann ich nichts dafür):

    #include <iostream>
    using namespace std;

    int main()
    {
    int mein_Alter = 39;
    int dein_Alter = 39;

    cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;

    mein_Alter++; // Postfix - Inkrement
    ++dein_Alter; // Präfix - Inkrement

    cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;

    cout << "Noch ein Jahr vergangen!" << endl;

    cout << "Ich bin " << mein_Alter++ << " Jahre alt!" << endl;
    cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl;

    cout << "Und nocheinmal ausgeben!" << endl;

    cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;

    return 0;
    }

    Die Ausgabe ist wie folgt:

    Ich bin: 39 Jahre alt.
    Du bist: 39 Jahre alt
    Ein Jahr ist vergangen...
    Ich bin: 40 Jahre alt.
    Du bist: 40 Jahre alt
    Noch ein Jahr ist vergangen
    Ich bin: 40 Jahre alt.
    Du bist: 41 Jahre alt
    Und noch einmal ausgeben.
    Ich bin: 41 Jahre alt.
    Du bist: 41 Jahre alt

    Nun zu meiner Frage: Die siebte Zeile in der Ausgabe müsste doch auch 41 Jahre ausgeben oder nicht?

    Falls ich etwas falsch gemacht habe, was ist falsch? Ich sehe den Fehler nicht...

    Falls es richtig ist, warum ist das so?

    Vielen Dank im Voraus für die Antworten.

    Gruß

    Max



  • #include <iostream>
    using namespace std;
    
    int main()
    {
    	int mein_Alter = 39;
    	int dein_Alter = 39;
    
    	cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl; //verwende hier '\n' statt endl
    	cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;
    
    	mein_Alter++;
    	++dein_Alter;
    
    	cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    	cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;
    
    	cout << "Noch ein Jahr vergangen!" << endl;
    
    	cout << "Ich bin " << mein_Alter++ << " Jahre alt!" << endl; // gibt zuerst mein_Alter aus, dann wird der Wert erhöht
    	cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl; // erhöht den Wert, dann wird dein_Alter ausgegeben
    
    	cout << "Und nocheinmal ausgeben!" << endl;
    
    	cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    	cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;
    
    	return 0; // nicht mehr notwendig, das ist der Standard-Rückgabewert
    }
    


  • Wenn du bei std::cout mein_alter++ ausgibst, dann gibt er den aktuellen Wert aus und inkrementiert dann erst den Wert dann um 1!

    Umgehen kann man das mit Präfix-Schreibweise oder, umständlicherweise, die Variable vor der Ausgabe inkrementieren!

    mein_Alter++; // Postfix - Inkrement
    ++dein_Alter; // Präfix - Inkrement
    
    cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;
    

    besser:

    cout << "Ich bin " << ++mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl;
    

    und kurzer Tip: verwende den Code-Tag, um Codeschnipsel einzufügen 🙂



  • Postfix- und Prefix-Operatoren haben zwar den gleichen Seiteneffekt, nämlich dass der Inhalt der Variablen um 1 erhöht/vermindert wird, jedoch verhalten sie sich unterschiedlich. Postfix gibt den aktuellen Wert zurück und Prefix den um 1 erhöhten/verminderten Wert. Du kannst es dir in etwa so vorstellen:

    int operator_postfix(int& ref)
    {
    	int tmp = ref;
    	ref = ref+1; // analog zu Minus.
    	return tmp;
    }
    
    int& operator_prefix(int& ref)
    {
    	ref = ref+1; // analog zu Minus.
    	return ref;
    }
    


  • Wie macht ihr das, dass der Quellcode in Farbe ist?

    Wie schon geschrieben, ich habe

    > den Quellcode kopiert
    > auf das C/C++ Kästchen geklickt
    > und den Quellcode eingefügt.

    Habe ich was falsch gemacht?



  • silent_max schrieb:

    Habe ich was falsch gemacht?

    Scheint so. Du markierst deinen gesamten Quellcode und klickst dann 1x auf das C/C++ Kästchen.



  • Ja ok.

    Dann erst einfügen, dann markieren und dann auf das Kästchen klicken.

    Gut ... kapiert.

    Und danke für die schnellen Antworten. Hat mich echt weiter gebracht...



  • So, ich versuch es auf ein neues.

    Quellcode kopiert, dann eingefügt und markiert und zuletzt auf C/C++ Kästchen geklickt

    [/cpp]#include <iostream>
    using namespace std;

    int main()
    {
    int mein_Alter = 30;
    int dein_Alter = 30;

    cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;
    cout << endl;
    cout << "Ein Jahr vergangen!" << endl;
    cout << endl;
    cout << "Ich bin " << ++mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl;
    cout << endl;
    cout << "Ein weiteres Jahr vergangen!" << endl;
    cout << endl;
    cout << "Ich bin " << ++mein_Alter << " Jahre alt!" << endl;
    cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl;
    cout << endl;
    return 0;
    }
    [cpp]



  • 😃 Da ist irgendwo der Hund drin. Klick einfach mal auf zitieren eines Beitrags, in dem es Quellcode gibt (z.B. meiner oben), dann siehst du, dass der Quellcode in [ cpp] und [ /cpp] eingerahmt ist.



  • #include <iostream>
    using namespace std;
    
    int main()
    {
    	int mein_Alter = 30;
    	int dein_Alter = 30;
    
    	cout << "Ich bin " << mein_Alter << " Jahre alt!" << endl;
    	cout << "Du bist " << dein_Alter << " Jahre alt!" << endl;
    	cout << endl;
    	cout << "Ein Jahr vergangen!" << endl;
    	cout << endl;
    	cout << "Ich bin " << ++mein_Alter << " Jahre alt!" << endl;
    	cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl;
    	cout << endl;
    	cout << "Ein weiteres Jahr vergangen!" << endl;
    	cout << endl;
    	cout << "Ich bin " << ++mein_Alter << " Jahre alt!" << endl;
    	cout << "Du bist " << ++dein_Alter << " Jahre alt!" << endl;
    	cout << endl;
    	return 0;
    }
    

    Es ist so verständlich ... erst

    und dann
    

    ...

    Jetzt hamas 🙂

    Jetzt nur eine Verständnisfrage... es ist doch aus Gründen der Übersicht generell besser den Präfix-Operator zu verwenden? Zumindest, so empfinde ich es, ist es doch verständlicher, kürzer und übersichtlicher, den Präfix-Operator zu verwenden



  • es ist nicht nur kürzer uns übersichtlicher, es wird auch eine temporäre variable gespart, wenn die nicht eh weg optimiert wird



  • Leider wird Anfängern immer erst der Postfixoperator beigebracht - steht dann völlig unnötig in allen for-Schleifen.



  • Dort, wo es keinen logischen Unterschied macht, sieht man es in C++ allgemein als gute Angewohnheit an, Präinkrement und -dekrement vorzuziehen. Das liegt vor allem daran, dass bei der Überladung dieser Operatoren (etwa für Iterator-Typen) eine Kopie gespart wird - eine typische Implementation könnte so aussehen:

    class my_iterator {
    ...
    
      // Präinkrement; Referenzrückgabe
      my_iterator &operator++()    { 
        increment();
        return *this;
      }
    
      // Postinkrement; Kopierückgabe
      my_iterator  operator++(int) {
        my_iterator old_value(*this); // Extraarbeit!
    
        increment();
    
        return old_value;
      }
    };
    

    Für Basistypen ist hier allerdings kein Unterschied zu erwarten; diese werden in aller Regel komplett in Registern verarbeitet, und ob jetzt erst erhöht und dann in den Speicher geschoben wird oder umgekehrt dürfte keinen großen Unterschied machen (zumal ein optimierender Compiler das eh intelligent behandeln dürfte).

    Dort, wo es einen logischen Unterschied macht, ist der Vergleich einer zwischen Äpfeln und Birnen. Ich würde allerdings anmerken, dass man Situationen, in denen es einen Unterschied macht, meistens vermeiden sollte, weil es sehr leicht ist, sich damit undefiniertes Verhalten bzw. unspezifizierte Werte einzuhandeln. Etwa ist die Ausgabe von

    int i = 0;
    
    std::cout << i++ << i++;
    

    durch den Standard nicht spezifiziert. Stichwort für Google: Sequence points.


Anmelden zum Antworten