Mathematische Berechnungen


  • Mod

    johny_legend schrieb:

    camper schrieb:

    hassanein schrieb:

    Wie aus dem kleinen Programm zu entnehmen ist möchte ich das Ergbnis dieser Aufgabe lösen: k *= i + --k ;

    ist undefiniert.

    War aber genau dein Kommentar.

    Da sehe ich keinen Widerspruch. Erklär mir bitte nochmal, wie du bei

    k *= i + k-- ;
    

    mit den Ausgangswerten i=3, k=4 auf das Ergebnis 27 kommst.
    Selbst wenn ich gutwillig bin, sind
    3, 21, 27 und 28
    denkbare Ergebnisse eines realen Compilers.
    Entsprechend den Transformationen

    // (1)
    int temp = k;
    k = k * i + k;
    k = temp - 1;
    
    // (2)
    int temp = k;
    k--;
    k = k * i + temp;
    
    // (3)
    k = k * i + k;
    k--;
    
    // (4)
    int temp = k * i + k;
    k--;
    k = temp;
    


  • Ich habe es wie Nagila Hawa mit Prioritäten begründet:

    k *= i + k-- ;

    (Priorität von Postfix --) <=> k*=i+k;
    k--;

    <=> k = k*(i+k);
    k = k-1;

    (für k=4, i=3) <=> k = 4*(3+4); // = 28
    <=> k = 28 - 1; // =27



  • [quote="johny_legend"]Ich habe es wie Nagila Hawa mit Prioritäten begründet:

    k *= i + k-- ;

    (Priorität von Postfix --) <=>

    k*=i+k;
    k--;
    

    <=>

    k = k*(i+k);
    k = k-1;
    

    (für k=4, i=3) <=>

    k = 4*(3+4); // = 28
     k = 28 - 1;  // =27
    

  • Mod

    johny_legend schrieb:

    Ich habe es wie Nagila Hawa mit Prioritäten begründet:

    Ich sehe hier keine Begründung. Zudem ist die Priorität von Postfix -- höher als die aller anderen Operatoren in dem Ausdruck. Entscheidend ist aber, das Postfix-Dekrement (ebenso wie die Zuweisung) neben einem Wert auch einen Seiteneffekt hat. Wann dieser Seiteneffekt (=die Veränderung des Wertes der Variablen) allerdings stattfindet, ist unspezifiziert (irgendwann zwischen dem vorhergehenden und dem nächsten Sequenzpunkt). Es ist schlicht falsch, zu sagen, dass bei Postfixinkrement zunächst der Wert zurückgegeben wird und danach der Wert des Objektes erniedrigt wird (es ist nur nah genug dran an der Wahrheit, dass man es in einer Einführung für Anfänger stehen lassen kann, um nicht zu sehr zu verwirren). Die Reihenfolge beider Teile einer Operation (Bestimmung des Wertes, Seiteneffekte) bleibt grundsätzlich unspezifiziert (abgesehen von Einschränkungen, die durch die Semantik der Operation impliziert sind).
    In unserem Falle ist der Ausdruck undefiniert, weil er das Objekt k zweimal zwischen den gleichen Sequenzpunkten modifiziert. Zudem findet im Teilausdruck

    k * ( i + k-- );
    

    ein Lesevorgang auf k statt (erster Faktor), der nicht dazu dient, den zu schreibenden Wert für k (bezogen auf das Dekrement) zu bestimmen (offensichtlich findet bei k-- ebenfalls ein Lesevorgang statt, das aber zwingend bevor der neue Wert geschrieben wird = Einschränkung durch Semantik). Der Schreibvorgang durch das Dekrement könnte abgeschlossen sein, bevor der erste Faktor bestimmt ist oder nicht.



  • hassanein schrieb:

    Wie aus dem kleinen Programm zu entnehmen ist möchte ich das Ergbnis dieser Aufgabe lösen: k *= i + --k ;

    das sieht auch für's menschliche auge 'undefiniert' aus.
    willst du sowas:

    k = k*i + k-1;
    k--;
    

    oder das

    k--;
    k = k*i + k;
    

    oder was ganz anderes?
    schreib doch mal hin, wie du's von hand ausrechnen würdest.
    🙂



  • camper schrieb:

    johny_legend schrieb:

    Ich habe es wie Nagila Hawa mit Prioritäten begründet:

    Ich sehe hier keine Begründung. Zudem ist die Priorität von Postfix -- höher als die aller anderen Operatoren in dem Ausdruck. Entscheidend ist aber, das Postfix-Dekrement (ebenso wie die Zuweisung) neben einem Wert auch einen Seiteneffekt hat. Wann dieser Seiteneffekt (=die Veränderung des Wertes der Variablen) allerdings stattfindet, ist unspezifiziert (irgendwann zwischen dem vorhergehenden und dem nächsten Sequenzpunkt). Es ist schlicht falsch, zu sagen, dass bei Postfixinkrement zunächst der Wert zurückgegeben wird und danach der Wert des Objektes erniedrigt wird (es ist nur nah genug dran an der Wahrheit, dass man es in einer Einführung für Anfänger stehen lassen kann, um nicht zu sehr zu verwirren). Die Reihenfolge beider Teile einer Operation (Bestimmung des Wertes, Seiteneffekte) bleibt grundsätzlich unspezifiziert (abgesehen von Einschränkungen, die durch die Semantik der Operation impliziert sind).
    In unserem Falle ist der Ausdruck undefiniert, weil er das Objekt k zweimal zwischen den gleichen Sequenzpunkten modifiziert. Zudem findet im Teilausdruck

    k * ( i + k-- );
    

    ein Lesevorgang auf k statt (erster Faktor), der nicht dazu dient, den zu schreibenden Wert für k (bezogen auf das Dekrement) zu bestimmen (offensichtlich findet bei k-- ebenfalls ein Lesevorgang statt, das aber zwingend bevor der neue Wert geschrieben wird = Einschränkung durch Semantik). Der Schreibvorgang durch das Dekrement könnte abgeschlossen sein, bevor der erste Faktor bestimmt ist oder nicht.

    Dem will ich auch nicht widersprechen. Die Tatsache, dass es laut Standard nicht definiert ist, ist nun wirklich nicht mehr zu diskutieren.
    Ich sage nur, dass es absehbar ist, wie der Compiler den Ausdruck k*=i+k--; aufarbeitet, und zwar nach den Prioritäten:

    Der Postfix-Dekrement-Operator, welcher hier die höchste Priorität hat, sieht laut Standard vor, dass zuerst der aktuelle Wert der Variable zurückgegeben wird, bevor dekrementiert wird:
    (k*=i+k)--

    Nächst kleinere Priorität hat der +-Operator:

    (k*=(i+k))--

    Und dann kommt eben (k=(k*(i+k)))-- raus.

    (ja, es ist syntaktisch falsch; soll aber der Verdeutlichung dienen. Die Klammern sollen die Prioritäten aufzeigen.)

    Du kannst mich aber gerne eines Besseren belehren und mir ein Beispiel zeigen, bei dem dieses Prinzip versagt.



  • johny_legend schrieb:

    Du kannst mich aber gerne eines Besseren belehren und mir ein Beispiel zeigen, bei dem dieses Prinzip versagt.

    Testcode:

    #include <stdio.h>
    
    int func (int k, int i) {
    	k *= i + k--;
    	return k;
    }
    
    int main (void) {
    	printf ("%d\n", func (4,3));
    	return 0;
    }
    

    Testcompiler:

    gcc version 3.4.5 (mingw special)
    

    Test [1]

    D:\temp>gcc ub.c -o ub -O0
    
    D:\temp>ub
    28
    

    Test [2]

    D:\temp>gcc ub.c -o ub -O1
    
    D:\temp>ub
    27
    

  • Mod

    ändert sich was, wenn du

    return k *= i + k--;
    

    schreibst?



  • Dann ist das Ergebnis immer 28 :p

    edit: read "immer" as "mit den Optimierungsstufen O0, O1, O2, O3, Os"



  • camper schrieb:

    ändert sich was, wenn du

    return k *= i + k--;
    

    schreibst?

    Dann müsste immer 28 rauskommen, weil nach return nicht mehr dekrementiert wird.

    Bzw.: Schade. Und ich war mir so sicher. 😞



  • johny_legend schrieb:

    Ich sage nur, dass es absehbar ist, wie der Compiler den Ausdruck k*=i+k--; aufarbeitet, und zwar nach den Prioritäten:

    Die Prioritäten haben nichts mit der Abarbeitungsreihenfolge zu tun. Das ist nur Syntax.



  • Hallo,

    ich würde dann gern wissen,

    wie k = 4; i = 3;

    x = i + k--;

    das ergebnis x = 7 sein kann;

    Ich habs so berechnet. Erst addiert und dann -1 subtrahiert
    i = 3 + 4-- <=> 6

    oder eigentlich müsste man 4 dekrementieren und dann addieren wegen der Priorität???? 😕

    würde sowieso alles 6 ergeben ob vor oder danach......
    bin mal gespannt.
    Gruß



  • Postfix bedeutet ja, dass zuerst der aktuelle Wert zurückgegeben wird und erst danach wird inkrementiert/dektrementiert.

    x = i + k--;

    // erst wird der Wert 4 an k zurückgegeben, dann wird addiert und dann erst wird
    // dekrementiert. x ist nach dieser Operation also 7 = 3(i) + 4(k).
    // nach dieser Zeile ist k aber = 3


  • Mod

    x = i + k--;
    

    Der Wert des Teilausdrucks

    k--
    

    ist der Wert, den die Variable k vor dem Dekrementieren hat, also 4.
    Der Wert des Teilausdrucks i ist der Zustand der Variablen i, also 3.
    Der Wert des Ausdrucks

    i + k--
    

    ist die Summe der beiden Operanden (=der Werte der entsprechenden Teilausdrücke), 3+4=7
    Der Wert des Zuweisungsausdrucks

    x = i + k--;
    

    ist der Wert des rechten Operanden, also 7.

    Der Ausdruck hat 2 Seiteneffekte:
    (1) der Wert der Variablen k wird durch den um 1 erniedrigten Wert, also 3, ersetzt.
    (2) der Wert der Variablen x wird durch den Wert 7 ersetzt.



  • Hallo,

    ich bin ein wenig neugierig oder vielleicht habe ich es hier überlesen, wer hat denn und wo eine solche Aufgabe mit diesen komischen Ausdrücken bekommen?
    Die Aufgabe ist doch vollkommen von der Realität entfernt. Ich persönlich finde es falsch, viele Operationen in eine Zeile zu packen. Zunächst ein mal, es ist unleserlich, aber - zähneknirschen - ok. Was ich aber noch schlimmer finde ist, dass man mit dem Debugger im Code wenige Stellen hat, ein Breakpoint zu setzen...



  • camper schrieb:

    Der Ausdruck hat 2 Seiteneffekte:
    (1) der Wert der Variablen k wird durch den um 1 erniedrigten Wert, also 3, ersetzt.
    (2) der Wert der Variablen x wird durch den Wert 7 ersetzt.

    was heisst hier 'seiteneffekte'. das ist ja wohl beabsichtigt, wenn man x=... und k-- da hinschreibt.



  • -fricky- schrieb:

    camper schrieb:

    Der Ausdruck hat 2 Seiteneffekte:
    (1) der Wert der Variablen k wird durch den um 1 erniedrigten Wert, also 3, ersetzt.
    (2) der Wert der Variablen x wird durch den Wert 7 ersetzt.

    was heisst hier 'seiteneffekte'. das ist ja wohl beabsichtigt, wenn man x=... und k-- da hinschreibt.

    Und wer sagt, das Seiteneffekte zwangsläufig was unbeabsichtigtes sind?



  • Tachyon schrieb:

    -fricky- schrieb:

    camper schrieb:

    Der Ausdruck hat 2 Seiteneffekte:
    (1) der Wert der Variablen k wird durch den um 1 erniedrigten Wert, also 3, ersetzt.
    (2) der Wert der Variablen x wird durch den Wert 7 ersetzt.

    was heisst hier 'seiteneffekte'. das ist ja wohl beabsichtigt, wenn man x=... und k-- da hinschreibt.

    Und wer sagt, das Seiteneffekte zwangsläufig was unbeabsichtigtes sind?

    ok, da hast du auch wieder recht. aber wenn bei x = i + k--; das x= und das k-- seiteneffekte sind, was ist dann der 'haupteffekt'?
    🙂



  • -fricky- schrieb:

    ok, da hast du auch wieder recht. aber wenn bei x = i + k--; das x= und das k-- seiteneffekte sind, was ist dann der 'haupteffekt'?
    🙂

    Wirkung
    🙂



  • -fricky- schrieb:

    Tachyon schrieb:

    Und wer sagt, das Seiteneffekte zwangsläufig was unbeabsichtigtes sind?

    ok, da hast du auch wieder recht. aber wenn bei x = i + k--; das x= und das k-- seiteneffekte sind, was ist dann der 'haupteffekt'?
    🙂

    Ausdrücke haben Eingaben, Ausgaben und Seiteneffekte. Die Eingabe von k-- ist k, die Ausgabe k. Der Seiteneffekt ist, dass k seinen Wert verändert.


Anmelden zum Antworten