Auswertungsreihenfolge von Parametern



  • Hey,

    soweit ich weiß, ist es ja nicht spezifiziert in welcher Reihenfolge Funktionsargumente ausgewertet werden, also z.B.

    foo(bar(), baz(), 1);
    

    da weiß man nicht in welcher Reihenfolge bar() und baz() ausgeführt werden. Wie sieht es aber hiermit aus?

    int i = 0;
    foo(++i, --i, i++);
    

    ... ist das hier auch unspezifiziert?


  • Mod

    Die Auswertungsreihenfolge jeglicher Funktionsargumente1 (nicht Parameter) ist nicht festgelegt. Das Programm hätte undefiniertes Verhalten.

    1) Ich kenne die Ausnahme, bitte nicht verkomplizieren.



  • Nur um das nochmal klarzustellen, Funktionsargumente sind sowas wie mein bar() und Parameter sowas wie mein ++i?

    Das heißt ich kann mir sicher sein, dass der Funktion foo() in meinem Beispiel immer mit den Parametern 1, 0, 0 aufgerufen wird?


  • Mod

    Nur um das nochmal klarzustellen, Funktionsargumente sind sowas wie mein bar() und Parameter sowas wie mein ++i?

    Argumente sind Werte die man an eine Funktion übergibt. Parameter sind die Variablen die diese Werte aufnehmen und mit denen in der Funktion gearbeitet wird. Wie du auch leicht hättest ergooglen können.



  • ajdsakjhdaskjdh schrieb:

    Nur um das nochmal klarzustellen, Funktionsargumente sind sowas wie mein bar() und Parameter sowas wie mein ++i?

    Nein, Argumente sind die Ausdrücke, die übergeben werden, und Parameter sind die Variablen, die die Werte der Argumente innerhalb der Funktion tragen.

    void foo(int a) { ... }  // a ist Parameter
    foo(42);  // 42 ist Argument
    
    void bar(int a = 42); // Quizfrage: 42 ist Defaultparameter oder Defaultargument?
    

    (Der Vollständigkeit halber: Manche Leute sagen Formalparameter für Parameter und Aktualparameter für Argument. Und manche glauben, dass die Begriffe austauschbar sind.)



  • Es gibt übrigens ein Proposal, was die Auswertungsreihenfolge spezifizieren will: http://isocpp.org/files/papers/n4228.pdf



  • Nathan schrieb:

    Es gibt übrigens ein Proposal, was die Auswertungsreihenfolge spezifizieren will: http://isocpp.org/files/papers/n4228.pdf

    Wo in dem void f().. Beispiel in der pdf ist etwas undefiniert?

    void f()  
    { 
        std::string s = "but I have heard it works even if you don’t believe in it" 
        s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don’t"), 6, ""); 
        assert(s == "I have heard it works only if you believe in it"); 
    }
    

  • Mod

    Frage1 schrieb:

    Nathan schrieb:

    Es gibt übrigens ein Proposal, was die Auswertungsreihenfolge spezifizieren will: http://isocpp.org/files/papers/n4228.pdf

    Wo in dem void f().. Beispiel in der pdf ist etwas undefiniert?

    void f()  
    { 
        std::string s = "but I have heard it works even if you don’t believe in it" 
        s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don’t"), 6, ""); 
        assert(s == "I have heard it works only if you believe in it"); 
    }
    

    Nicht undefiniert aber unspezifiziert: je nachdem wann find durchgeführt wird, werden unterschiedliche Teile des Strings ersetzt.



  • Versteh ich nicht.

    Die replace() werden ja nacheinander ausgeführt.

    replace(0, 4, "")
    dann replace(s.find("even"), 4, "only") (s nach dem ersten replace)
    dann replace(s.find(" don’t"), 6, "") (s nach dem zweiten replace)

    Wo gibt es da mehrere Möglichkeiten?!


  • Mod

    Die replace() werden ja nacheinander ausgeführt.

    Und was ist mit den find s?



  • Frage1 schrieb:

    Versteh ich nicht.

    Die replace() werden ja nacheinander ausgeführt.

    Es geht nicht um die replaces, sondern um die finds.



  • Na zuerst das find() im ersten replace, dann das find() im zweiten.



  • Du hast 5 Aufrufe, 2mal find, 3mal replace.

    s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don’t"), 6, "");

    Es ist klar, dass die replaces in ihrer Reihenfolge ausgeführt werden müssen. Es ist auch klar, dass das erste find vor dem zweiten Replace und das zweite find vor dem dritten replace ausgeführt werden muss. Darüber hinaus ist die Reihenfolge nicht spezifiziert, es gibt also folgende mögliche Ausführungsreihenfolgen:

    find find replace replace replace
    find replace find replace replace
    replace find find replace replace
    find replace replace find replace
    replace find replace find replace

    Bei den ersten dreien können die finds auch vertauscht sein, das macht also 8 Möglichkeiten, wenn ich keine vergessen habe. Einige werden gleiche Effekte haben, aber das spielt keine Rolle.



  • Und genau aus diesem Grund wollen die das definieren. 😃



  • Achso, verstehe.
    In solch einem zusammengesetzten Ausdruck steht überhaupt nicht fest, wann die Argumente ausgewertet werden.

    Weiß jemand, ob/wie es in Visual Studio festgelegt ist?



  • Ich weiß es nicht, aber ich gehe davon aus, dass es nicht festgelegt ist. Warum sollte man sowas machen? Das behindert doch den Optimierer.


Anmelden zum Antworten