Frage zu <<



  • Hallo Forum,

    warum geht:
    cout << "a" << "b" << "c";
    und
    cout << myfunc() << myfunc() << myfunc();
    gibt Probleme bei der Auswertungsreihenfolge?

    Vielen Dank

    Persy



  • Weil es darauf ankommt was myfunc() zurück gibt, genauer gesagt welchen Typ es zurück gibt. Wenn es keiner der Standardtypen ist, mußt du den <<-Operator für ostream überladen, was sehr einfach ist. Dann funktioniert das auch.



  • Artchi schrieb:

    Weil es darauf ankommt was myfunc() zurück gibt, genauer gesagt welchen Typ es zurück gibt. Wenn es keiner der Standardtypen ist, mußt du den <<-Operator für ostream überladen, was sehr einfach ist. Dann funktioniert das auch.

    Auch mit Standardtypen funktioniert es nicht, sondern wird stack-mäßig von hinten aufgerollt. Ich kriege also die genau umgekehrte Reihenfolge. Zumindest beim MS-Compiler (keine Ahnung, ob sowas implementierungsspezifisch ist).



  • Persy schrieb:

    warum geht:
    cout << "a" << "b" << "c";
    und
    cout << myfunc() << myfunc() << myfunc();

    Weil operator<<() den Stream als Ergebnis liefert:

    std::stream &operator<<(std::stream &lhs, const char *rhs) {
    
       // rhs nach lhs ausgeben
    
       return lhs;
    }
    

    Persy schrieb:

    gibt Probleme bei der Auswertungsreihenfolge?

    Edit: S. _matze und Artchi

    Stefan.



  • Persy schrieb:

    warum geht:
    cout << "a" << "b" << "c";
    und
    cout << myfunc() << myfunc() << myfunc();
    gibt Probleme bei der Auswertungsreihenfolge?

    Was für Probleme denn? Ich rate mal, dass Dein myfunc Seiteneffekte besitzt und unterschiedliche Ergebnisse liefert. ZB so etwas:

    int myfunc()
    {
      static int i=0;
      return ++i;
    }
    

    Und wahrscheinlich würdest Du hier folgende Ausgabe erwarten:

    123
    

    Allerdings wird nirgendswo im C++ Standard festgelegt (bis auf ein paar Ausnahmen), in welcher Reihenfolge Teilausdrücke ausgewertet werden. Daher kannst Du Dich hier auf nichts verlassen.

    Der Compiler kann das intern so zerlegen

    tmp1 = myfunc()
    tmp2 = myfunc()
    tmp3 = myfunc()
           cout << tmp1 << tmp2 << tmp3
    

    oder aber so

    tmp3 = myfunc()
    tmp2 = myfunc()
    tmp1 = myfunc()
           cout << tmp1 << tmp2 << tmp3
    

    oder aber so

    tmp2 = myfunc()
    tmp1 = myfunc()
    sref = cout << tmp1 << tmp2
    tmp3 = myfunc()
           sref << tmp3
    

    ...ist alles erlaubt...

    Gruß,
    SP



  • Das war gerade in der Vorlesung. Es hieß die Reihenfolge der Abarbeitung wäre nicht genau definiert. Hier ein Beispiel:

    #include <iostream>
    
    using namespace std; 
    
    char myfunc(int a) {
        return (char)(64 + a);
    }
    
    int main() {
    	cout << "a" << "b" << "c" << endl;
    	cout << myfunc(1) << myfunc(2) << myfunc(3) << endl;
    	return 0;
    }
    

    Es funktioniert jedoch wie vorgesehen (g++ Kompiler): "abc" und dann "ABC"
    Habt Ihr ne Ahnung was da gemeint ist?

    EDIT: Ich sehe gerade Sebastians Antwort. Wenn die Auswertungsreihenfolge unklar ist, wäre das aber nicht intuitiv. Laut Matze würde der MS Kompiler CBA ausegeben. Das wäre ziemlich unerwartet. Wenn der Prof das in der Vorlesung extra erwähnt hat muß man sich bei C++ wohl daran gewöhnen...

    Vielen Dank 🙂

    Persy



  • #include <iostream>
    
    using namespace std;
    
    char glob='A';
    
    char myfunc(int a) {
        return glob++;
    }
    
    int main() {
        cout << "a" << "b" << "c" << endl;
        cout << myfunc(1) << myfunc(2) << myfunc(3) << endl;
        return 0;
    }
    

    Ausgabe CBA
    Und jetzt denk nach, warum Dein Prog bei jeder Auswertungsreihenfolge ABC ausgibt und deswegen gar kein diesbezüglicher Test ist.



  • Stimmt, CBA jetzt auch bei mir. Da habe ich die static oder globale Veriable vergessen. Wie bei Volkard ist es richtig. In Unterausdrücke werden also bei beiden Kompilern in umgekehrter Reihenfolge (also von rechts nach links) ausgewertet.

    Vielen Dank 🙂

    Persy


Anmelden zum Antworten