bringt der compiler die Warnung weil nicht klar ist wann er das ++ macht? *ptr++ = *ptr*1.5; was ich mir vorstellte: dass er das ++ nach der Zuweisung macht
die frage ist, ob *ptr nach dem = den wert vor oder nach dem ptr++ hat. Aber zum glück kann man sotwas auch lesbarer schreiben.
Bernd schrieb: > bringt der compiler die Warnung weil nicht klar ist wann er das ++ > macht? > *ptr++ = *ptr*1.5; > > was ich mir vorstellte: dass er das ++ nach der Zuweisung macht Was du dir vorstellst ist irrelevant. Relevant ist, was die Sprachdefinition dazu zu sagen hat. Und die ist eindeutig es ist nicht definiert, wann genau innerhalb einer Sequence das Ergebnis nach dem ++ in die Variable zurückgeschrieben wird. Fest steht nur, dass es vor dem nächsten Sequence Point zu geschehen hat. Und der ist in diesem Fall der ; D.h. Irgendwann in der Ausführung des Statements muss ptr mit dem neuen Wert beschrieben werden, spätestens dann wenn alles andere aus diesem Statement abgearbeitet wurde. D.h. das nächste, darauffolgende Statement kann darauf vertrauen, dass in ptr dann bereits der erhöhte Wert enthalten ist. Aber: In dem Zwischenraum vom Beginn des Statements bis zu dessen Ende hat der Compiler alle Freiheiten, das Rückschreiben des erhöhten Wertes dort anzusiedeln, wo es ihm am besten in den Kram passt.
Peter schrieb: > Aber zum glück kann man sotwas auch lesbarer schreiben. Man könnte es aber auch noch unlesbarer schreiben:
1 | *(ptr++)++; |
SCNR. :)
Karl heinz Buchegger schrieb:
danke für die Erklärung
d.h. als Konsequenz: sobald eine Variable mehr als ein Mal in einer
Sequenz auftaucht -> Finger weg von ++, bei 1x Vorkommen geht's
Bernd schrieb: > Karl heinz Buchegger schrieb: > > danke für die Erklärung > d.h. als Konsequenz: sobald eine Variable mehr als ein Mal in einer > Sequenz auftaucht -> Finger weg von ++, bei 1x Vorkommen geht's Noch allgemeiner! Finger weg von allen implizten Annahmen, die du über die Abarbeitung von Teilausdrücken eines Statements triffst! i = foo() + bar(); wird zuerst foo() aufgerufen oder zuerst bar()? Antwort: Es ist nicht definiert. Wenn zwischen den Funktionen ein Zusammenhang besteht, so dass foo vor bar aufgerufen werden muss, dann hast du keine Garantie, dass dies auch tatsächlich so passiert. foo( func1(), func2() ); eine Funktion wird aufgerufen, die 2 Argumente bekommt. So wie in foo( 3, 4 ); nur dass in diesem Fall die Argumente die Returnwerte von weiteren Funktionsaufrufen sind. Wird zuerst func1() aufgerufen oder func2()? Antwort: Es ist nicht definiert. i = 3; printf( "%d %d\n", i, i++ ); wie lautet die Ausgabe? Antort: Es ist nicht definiert. 3 3 ist eine mögliche Antwort, genauso wie 4 3
>Finger weg von allen implizten Annahmen, die du über die Abarbeitung von >Teilausdrücken eines Statements triffst! Wobei im Falle von && und || die Reihenfolge ausnahmsweise definiert ist. Da werden die Operanden von links nach rechts ausgewertet.
Karl heinz Buchegger schrieb: > es ist nicht definiert, wann genau innerhalb einer Sequence das > Ergebnis nach dem ++ in die Variable zurückgeschrieben wird. Es ist sogar noch weniger definiert als das. So wäre das Verhalten nämlich lediglich "unspecified", aber es ist "undefined". Es geht also so weit, daß was beliebiges passieren kann, nicht nur daß die Reihenfolge unbestimmt ist. Karl heinz Buchegger schrieb: > Finger weg von allen implizten Annahmen, die du über die Abarbeitung > von Teilausdrücken eines Statements triffst! > > i = foo() + bar(); > > wird zuerst foo() aufgerufen oder zuerst bar()? > > Antwort: Es ist nicht definiert. Das wiederum ist nicht "undefined", sondern nur "unspecified". > foo( func1(), func2() ); > eine Funktion wird aufgerufen, die 2 Argumente bekommt. So wie in > foo( 3, 4 ); > nur dass in diesem Fall die Argumente die Returnwerte von weiteren > Funktionsaufrufen sind. > > Wird zuerst func1() aufgerufen oder func2()? > > Antwort: Es ist nicht definiert. Ebenfalls unspecified. > i = 3; > printf( "%d %d\n", i, i++ ); > wie lautet die Ausgabe? > > Antort: Es ist nicht definiert. > 3 3 ist eine mögliche Antwort, genauso wie > 4 3 Das ist soweit ich weiß wieder undefined, weil kein Sequenzpunkt zwischen der Auswertung der einzelnen Argumente liegt. Somit ist auch jede beliebige andere Antwort oder ein kompletter Crash "korrekt". Huch schrieb: > Wobei im Falle von && und || die Reihenfolge ausnahmsweise definiert > ist. Da werden die Operanden von links nach rechts ausgewertet. Aber Vorsicht: Abhängig vom Wert des linken Operanden wird der rechte evtl. auch gar nicht ausgewertet.
Karl heinz Buchegger schrieb: > Bernd schrieb: >> bringt der compiler die Warnung weil nicht klar ist wann er das ++ >> macht? >> *ptr++ = *ptr*1.5; >> >> was ich mir vorstellte: dass er das ++ nach der Zuweisung macht > > Was du dir vorstellst ist irrelevant. > Relevant ist, was die Sprachdefinition dazu zu sagen hat. Ist dann eigentlich *ptr++ *= 1.5; eindeutig?
Klaus Falser schrieb: > Ist dann eigentlich > > *ptr++ *= 1.5; > > eindeutig? Ja, ist es. (Hinweis: Es passiert nicht das, was du jetzt wahrscheinlich denkst das passieren sollte. Das ++ wirkt auf den Pointer und nicht auf den Wert an der Stelle *ptr) (*ptr)++ *= 1.5; währe wieder undefiniert Da es Rolf schon aufgebracht hat: Ich wollte mir das eigentlich schenken, um die Sache nicht weiter zu verkomplizieren. Im C-Standard wird zwischen 2 Dingen unterschieden: * unspecified * undefined Der Unterschied ist ganz einfach der: Wenn etwas undefined ist, dann kann alles mögliche passieren. Die Festplatte kann formatiert werden, Angela Merkel verteilt ihr Gehalt an Arbeitslose, der Untergang des besiedelten Abendlandes so wie wir es kennen. Alles ist möglich. Inklusive dass sich die Codestelle so verhält, wie es ein bestimmter Programmierer erwartet. unspecified hingegen ist die etwas harmlosere Form. D.h. die im C-Standard beabsichtigte Funktionalität muss zwar erreicht werden, aber im Standard wird nicht weiter festgelegt, wie das genau zu geschehen hat. Die Reihenfolge der Argumentauswertung bei Funktionsaufrufen ist zb unspecified. Das bedeutet, das der Standard keine Reihenfolge vorschreibt. Von Rechts nach Links, von Links nach Rechts, in beliebiger Reihenfolge, alles ist möglich, so wie es der Compilerbauer für richtig hält. Aber die grundsätzliche Funktionalität, nämlich dass alle Argumente ausgewertet werden, ist gewährleistet. Nur halt nicht in welcher Reihenfolge. Wenn dein Programm daher davon abhängt, dann wird es zwar auf die Nase fallen, aber ein Weltuntergang kann nicht mehr passieren. Unspecified Dinge sind auch zu dokumentieren. D.h. der Compilerbauer kann nicht bei einem Funktionsaufruf die Argumentauswertung so rum machen und bei einem anderen anders. Er muss sich einmal für etwas entscheiden, das dokumentieren und dann dabei bleiben. Das es natürlich nicht sehr schlau ist, sich auf unspecified Dinge zu verlassen, versteht sich von selbst. Denn niemand garantiert, dass die Dinge auf einem anderen Compilerm, in der nächsten Compilerrelease sich immer noch genau gleich verhalten.
Karl heinz Buchegger schrieb: > (Hinweis: Es passiert nicht das, was du jetzt wahrscheinlich denkst das > passieren sollte. Das ++ wirkt auf den Pointer und nicht auf den Wert an > der Stelle *ptr) Naja, ich wusste schon, was passiert :-) Dazu programmiere ich zu lange in C, aber jetzt hatte mich doch der Zweifel gepackt.
Karl heinz Buchegger schrieb: > Unspecified Dinge sind auch zu dokumentieren. D.h. der > Compilerbauer kann nicht bei einem Funktionsaufruf die > Argumentauswertung so rum machen und bei einem anderen anders. Er muss > sich einmal für etwas entscheiden, das dokumentieren und dann dabei > bleiben. Wäre das dann nicht "implementation defined"? Oder ist das das selbe? Oder gibts den Ausdruck im C-Standard doch gar nicht?
Klaus schrieb: > Karl heinz Buchegger schrieb: >> Unspecified Dinge sind auch zu dokumentieren. D.h. der >> Compilerbauer kann nicht bei einem Funktionsaufruf die >> Argumentauswertung so rum machen und bei einem anderen anders. Er muss >> sich einmal für etwas entscheiden, das dokumentieren und dann dabei >> bleiben. > > Wäre das dann nicht "implementation defined"? Doch, das wäre es. "unspecified" ist genau wie "implementation defined", nur mit dem Untschied, daß es nicht im Compiler-Handbuch dokumentiert sein muß.
Klaus schrieb: > Karl heinz Buchegger schrieb: >> Unspecified Dinge sind auch zu dokumentieren. D.h. der >> Compilerbauer kann nicht bei einem Funktionsaufruf die >> Argumentauswertung so rum machen und bei einem anderen anders. Er muss >> sich einmal für etwas entscheiden, das dokumentieren und dann dabei >> bleiben. > > Wäre das dann nicht "implementation defined"? Oder ist das das selbe? > Oder gibts den Ausdruck im C-Standard doch gar nicht? Du hast schon recht Unspecified behaviour / ISO C99 3.4.4 behavior where [the standard] provides two or more possibilities and imposes no further requirements on which is chosen in any instance Implementation-defined behavior / ISO C99 3.4.1 unspecified behavior where each implementation documents how the choice is made Durch die Dokumentation wird aus unspecified ein implementation defined.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.