Forum: Compiler & IDEs operation on 'ptr' may be undefined


von Bernd (Gast)


Lesenswert?

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

von Peter (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Aber zum glück kann man sotwas auch lesbarer schreiben.

Man könnte es aber auch noch unlesbarer schreiben:
1
*(ptr++)++;

SCNR. :)

von Bernd (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


Lesenswert?

>   katze(  lebt(), tot() );

SCNR

von Huch (Gast)


Lesenswert?

>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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von Klaus Falser (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Klaus Falser (Gast)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

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?

von Rolf Magnus (Gast)


Lesenswert?

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ß.

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.