Bug in C++?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Bug in C++?

    Nachdem ich fast nen Monat annem bug in meinem aktuellen Projekt verzweifelt bin hab ich heute die Ursache gefunden. Diese Ursache ist ein ?Fehler? in C++.
    Nehmen wir ein Beispielprogramm:
    __________________________________
    #include <iostream>
    using namespace std;

    int zahl;

    int getzahl()
    {
    zahl++;
    return zahl;
    }

    void main ()
    {
    zahl = 0;
    cout << getzahl() << " " << getzahl() << " " << getzahl() << " " << getzahl();
    }

    ------------------------------------------------------

    nach Plan würde man die Ausgabe 1 2 3 4 erwarten,
    ausgegeben wird jedoch 4 3 2 1. (bei mir führte der fehler dazu dass ein script falschherum eingelesen wurde, was SEHR merkwürdige Fehler abgab)

    Anscheinend werden die return werte für diesen einen cout-befehl zuerst aufgestapelt und dann mit verkehrtherum ausgewertet.
    Dies passiert allerdings nur wenn das ganze innerhalb eines befehls passiert.

    cout << getzahl();
    cout << getzahl();
    cout << getzahl();
    cout << getzahl();

    würde er erwartungsgemäß 1 2 3 4 ausgeben.



    beispielsource zu der eben genannten Variante:
    #include <iostream>
    using namespace std;

    int zahl;

    int getzahl()
    {
    zahl++;
    return zahl;
    }

    void main ()
    {
    zahl = 0;
    cout << getzahl() << " ";
    cout << getzahl() << " ";
    cout << getzahl() << " ";
    cout << getzahl() << " ";
    }



    Ist das tatsächlich ein unbeabsichtigter Effekt in C++?
    Mache ich etwas falsch?
    Wichtiger, kann man das ganze so umschreiben dass man getzahl() in der Art vom 1. code verwenden kann?
    (Ohne dabei cout in die func zu haun natürlich, sonst würd ich ja nicht fragen)

    ------------------------------------------------------------------------
    nochwaszumnachdenken:

    #include <iostream>
    using namespace std;

    int zahl;

    int getzahl()
    {
    zahl++;
    cout << " "; //<------- !hinzugefügte zeile!
    return zahl;
    }

    void main ()
    {
    zahl = 0;
    cout << getzahl() << getzahl()<< getzahl()<< getzahl();
    }

    gibt:
    4321
    also
    SPACE SPACE SPACE SPACE 4321 aus
    --------------------------------------------------------------------------

    Ich hoffe einer von euch hat da mehr Ahnung als ich...
  • Tja, das sind die Tiefen der Programmierung.
    Die Zahlen komme völlig zu recht in der falschen Reihenfolge raus. Das hängt mit den Prioritäten zusammen, die man in diversen Tabellen nachlesen kann. Außerdem solltes du keine globale Variable verwenden...

    Bei der verschachtelten cout-Anweisung erfodern die Regeln, dass die einzelnen Ausgaben zurückgestellt werden, bis die Funktionsaufrufe erledigt sind. Diese haben nämlich eine höhere Priorität, als die << Operatoren. Die return-Ergebnisse landen bei verschachtelte Unterprogrammaufrufen auf einem Stack (Stapel): zuerst wird also die 1 auf dem Stack abgelegt, dann die 2, dann 3 und dann 4. Somit sieht der Stack so aus:
    4 (oben, also zuletzt abgelegter Wert)
    3
    2
    1 (unten, also zuerst abgelegter Wert).

    Diese Werte holen sich dann die Ausgabeoperatoren. Ein Stack wird immer von oben nach unten gelesen. Daher erscheint zuerst die 4, dann die 3 und so weiter auf dem Bildschirm.

    Dises Verhalten ist in C++ immer so, dagegen gibt es kein Mittel. Das ist so gewollt. Irgendwie muss man ja solche Ketten von Aufrufen ja auflösen. Diese Festlegung wurde halt wie oben beschrieben getroffen.

    Du musst also tatsächlich verschiedene cout-Anweisungen verwenden.

    Um das nochmal deutlich zu machen:
    was viele vergessen (oder nicht wissen), ist, dass Operatoren auch nur Unterprogramme sind. Sie werden bloss als Operator geschrieben. Der << Operator der Klasse ostream sieht so aus:

    class ostream {
    ....
    ostream & operator << (int wert);
    ....
    }

    Eine Ausgabe
    cout << getzahl();
    entspricht demnach von der Logik:
    cout . << (getzahl()); // Funktionsaufruf

    Grüße
    Michael
  • thx für die ausführliche antwort, meine vermutungen sehen sich bestätigt, endlich kann ich wieder einschlafen ohne schreiend aufwachen zu müssen.

    In meinem Proggie hab ich die koordinaten für ein sprite so ähnlich wie folgt einlesen lassen:
    //(int xpos ,int ypos )
    Sprite[12].SetPosition (getzahl(),getzahl());

    Geht das besser umzuschreiben als:

    Sprite[12].SetPosition(getzahl(), Sprite[12].gety());
    Sprite[12].SetPosition(Sprite[12].getx(), getzahl());

    ?
  • problem nicht mehr wichtig, ich musste aus technischen gründen eh ne extra setx und sety func in die Spriteklasse integrieren, da kann ich sie getrost auch hierfür verwenden