Prüfungsfrage

Gast #3496784
Lesenswert?

Hallo,

wir haben heute unsere Prüfung in "Grundlagen der Programmierung" 
gehabt.
Dabei tauchte folgende Aufgabe auf:
1
#include <stdio.h>
2

3
int main()
4
{  int *n;
5
  int m[2][3] ={{2,5,8},{4,8,9}};
6
  n-- = *(m+1)+2;
7
  printf("%d\n", *n);
8
  n--;
9
  printf("%d\n", *n);
10
}

Man sollte bestimmen, was das Programm ausgibt. Allerdings habe ich das 
gerade mit dem gcc getestet und festgestellt, dass man "n-- =" gar nicht 
machen kann. Hat einer von euch eventuell eine seriöse Begründung dafür? 
Oder noch besser einen Literatur Hinweis, wo etwas dazu steht?

Vielen Dank im Voraus :)
Gast #3496807
Lesenswert?

Die Antwort ist "nichts", da das Programm Fehler enthält. Ihr habt ja 
einen lustigen Lehrer ;-).

Student schrieb:
> Hallo,
>
> wir haben heute unsere Prüfung in "Grundlagen der Programmierung"
> gehabt.
> Dabei tauchte folgende Aufgabe auf:
> ...
> Man sollte bestimmen, was das Programm ausgibt. Allerdings habe ich das
> gerade mit dem gcc getestet und festgestellt, dass man "n-- =" gar nicht
> machen kann. Hat einer von euch eventuell eine seriöse Begründung dafür?
> Oder noch besser einen Literatur Hinweis, wo etwas dazu steht?
>
> Vielen Dank im Voraus :)
Gast #3496930
Lesenswert?

lutz h. schrieb:
> was wird als nächtes berechnet?
Genau.

Das ist m. E. der relevante Satz:
> If a side effect on a scalar object is unsequenced relative
> to [...] a value computation using the value of the same
> scalar object, the behavior is undefined.
> [...]
> i = v[i++]; // the behavior is undefined
> i = i++ + 1; // the behavior is undefined

Sprich, wenn ein increment oder decrement an einer Variablen dran ist, 
dann darf sie im kompletten Ausdruck exakt dieses eine Mal vorkommen.
> int j = i++ + ++i;
ist genauso undefiniert.
#3496949
Lesenswert?

Bülent C. schrieb:
> Also, bei ++i wird doch einfach inkremmentiert, richtig?

++i ist die Kurzform von
  i += 1
und i += ... ist die Kurzform von
  i = i + ...

Also ist
  i += ++i
eigentlich
  i = i + (i = i + 1)

Wenn nun zwischen 2 Sequence Points (ggf. nachschlagen) mehr als eine 
Zuweisung auf die gleiche Variable erfolgt, dann ist undefiniert, wann 
genau welche davon erfolgt. Zudem ist hier undefiniert, ob die rechte 
Zuweisung vor oder nach dem Zugriff auf das "i" vor dem ersten "+" 
erfolgt.
Gast #3496957
Lesenswert?

> The value of a postfix ++ expression is the value of its operand.
> [ Note: the value obtained is a copy of the original value —end note ]

> The operand of prefix ++ is modified by adding 1 [...] The result
> is the updated operand;

Hm, aber vielleicht kann ich dir einfacher kommen...
> i++ + ++i
müsste etwas anderes sein als
> ++i + i++
und das verletzt das Kommutativgesetz der Addition.

Es steht einfach nirgends, in welcher Reihenfolge ein Compiler einen 
Ausdruck auszuwerten hat, weil eben kein "sequence point" dazwischen 
ist. Der Compiler darf beispielsweise die Parameter eines 
Funktionsaufrufs auch in einer beliebigen Reihenfolge auswerten.
Gast #3496965
Lesenswert?

>Und was ist der Unterschied zwischen i++ und ++i?

pre- bzw. postinkrement

z.B.
int Nummer [ 3 ];
int i;

i = 0;
Nummer [ i++ ] := 5;       Bewirkt Nummer [ 0 ] = 5 | erst [i] dann + 1
Nummer [ i++ ] := 6;       Bewirkt Nummer [ 1 ] = 6 | erst [i] dann + 1

im Gegensatz zu:

i = 0;
Nummer [ ++i ] := 5;       Bewirkt Nummer [ 1 ] = 5 | erst + 1 dann [i]
Nummer [ ++i ] := 6;       Bewirkt Nummer [ 2 ] = 6 | erst + 1 dann [i]

oder so
Gast #3496973
Lesenswert?

A. K. schrieb:
> Max H. schrieb:
>> Und was ist der Unterschied zwischen i++ und ++i?
>
>   ++i
> ist
>   i = i + 1
>   return i
> und
>   i++
> ist
>   temp = i
>   i = i + 1
>   return temp

Das erklärt es meiner Meinung nach nicht vollständig.
1
    i = 0;
2
    printf ("%d\n", i++);

Ergibt als Ausgabe 0.
1
    i = 0;
2
    printf ("%d\n", ++i);

Ergibt als Ausgabe 1.
#3496989
Lesenswert?

Student schrieb:
> Falls das falsch verstanden wurde, Die Aufgabe war nicht zum abtippen.
> Ich musste die in einer realen Prüfung auf Papier lösen. Ohne Computer.

Das war schon klar. Es ändert aber nichts daran, dass n-- keine Lvalue 
ist, also nicht links von einer Zuweisung stehen darf. Der gezeigte Code 
läuft folglich auf eine Fehlermeldung des Compilers, wenn der genau und 
nur Standard-C verdaut.

Die Frage ist also nicht beantwortbar, da es kein ausführbares Programm 
geben kann. Es ist zwar vermutlich das gemeint, was Jonas schrieb, aber 
wenn du in einer realen Prüfung auf eine solche Frage stösst, und es 
keine Fangfrage ist, dann sitzt du ziemlich in der Tinte.
Gast #3496992
Lesenswert?

Du willst eine seriöse Quelle? :)
Nur l-Values können Ziel einer Zuweisung sein, wie der gcc korrekt 
feststellt:
> test.cpp:6:7: error: lvalue required as left operand of assignment
>    n-- = *(m+1)+2;
>        ^

Und der C++-Standard sagt zu "--":
> 5.2.6 Increment and decrement [expr.post.incr]
> [...] The operand shall be a modifiable lvalue.
> [...] The result is a prvalue.
> [...]

Ein pr-Value ist nunmal kein l-Value.
Gast #3497203
Lesenswert?

In solchen Fällen würde ich schreiben, dass
1.) die Originalaufgabe nicht kompilierbar ist, weil...

2.) nach Anpassung an die C-Sprachvereinbarung 8 und 4 angezeigt wird.

Fertig.
Lösungsorientiertes arbeiten.
#3497559
Lesenswert?

Letzendlich wird immer das wiederholt was ich schon mehrfach geschrieben 
hatte..... Unterschied zwischen ++i und i++ und noch ein paar andere 
Sachen fallen dadrunter


#include<stdio.h>

int main() {
  int i = 1;
  i += i++ + ++i;
  printf ("Wert von i: %d\n", i);
  return 0;
}


Mir wurde bis dato nicht schlüßig erklärt, warum das nicht funktionieren 
sollte...Also rein theoretisch und auch praktisch ist i=7!
Gast #3497564
Lesenswert?

Bülent C. schrieb:
> Mir wurde bis dato nicht schlüßig erklärt, warum das nicht funktionieren
> sollte...Also rein theoretisch und auch praktisch ist i=7!

i += i++ + ++i;

weil C nur festlegt das das ++ beim ; erledigt sein muss. Es ist also 
genauso zulässig das i sich für das ++i noch nicht geändert hat also 
immer noch 1 ist.
#3497574
Lesenswert?

Peter II schrieb:
> Bülent C. schrieb:
>> Mir wurde bis dato nicht schlüßig erklärt, warum das nicht funktionieren
>> sollte...Also rein theoretisch und auch praktisch ist i=7!
>
> i += i++ + ++i;
>
> weil C nur festlegt das das ++ beim ; erledigt sein muss. Es ist also
> genauso zulässig das i sich für das ++i noch nicht geändert hat also
> immer noch 1 ist.

Resultat?
#3497620
Lesenswert?

Bülent C. schrieb:
> Resultat?

Wie wärs mit 2?
  temp = i + 1; // erste Operation
  ...uninteressantes Zeugs...
  i = temp;     // letzte Operation

Ein reales Ergebnis eines realen Compilers ist kein Beweis dafür, dass 
eine Operation definiert ist.

Die Warnungen eines realen Compilers wie GCC sind allerdings ein 
ziemlich deutliches Indiz dafür, dass das Ergebnis qua Standard 
undefiniert ist.

Vielleicht hilft es dir, dass der C Standard
  i = ++i + 1;
ausdrücklich als undefiniert erklärt. Dieses Statement steht explizit 
bei C99 als Beispiel dafür drin.
#3497758
Lesenswert?

A. K. schrieb:
> Bülent C. schrieb:
>> Resultat?
>
> Wie wärs mit 2?
>   temp = i + 1; // erste Operation
>   ...uninteressantes Zeugs...
>   i = temp;     // letzte Operation
>
> Ein reales Ergebnis eines realen Compilers ist kein Beweis dafür, dass
> eine Operation definiert ist.
>
> Die Warnungen eines realen Compilers wie GCC sind allerdings ein
> ziemlich deutliches Indiz dafür, dass das Ergebnis qua Standard
> undefiniert ist.
>
> Vielleicht hilft es dir, dass der C Standard
>   i = ++i + 1;
> ausdrücklich als undefiniert erklärt. Dieses Statement steht explizit
> bei C99 als Beispiel dafür drin.

Sorry, aber ich habe immer noch keinen Beleg dafür, warum es nicht 
definierbar sein soll.
Vielleicht noch mal als Anregung.... ++i inkrementiert nur....i++ 
erzeugt ein temporäres Object mit i und i inkremmentiert und
der temporäre Wert zurueckgegeben.
Spielt hier denn nich eine Reihenfolge eine Rolle? Zb eine art 
Evaluationsreihenfolge?

Unabhängig davon...mein gcc gibt nicht mal ne Warnmeldung aus und spuckt 
als Ergebnis ne 7 aus.
#3497776
Lesenswert?

A. K. schrieb:
> Ich hoffen das reicht. Quelle C99 draft n1256.

Schaumal was zur Fußnote 72 steht ;-)

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

Was Gefällt Dir nicht an meinem letzten comment:
++i inkrementiert nur....i++
erzeugt ein temporäres Object mit i und i inkremmentiert und
der temporäre Wert zurueckgegeben.
Spielt hier denn nich eine Reihenfolge eine Rolle? Zb eine art
Evaluationsreihenfolge?
#3497778
Lesenswert?

Bülent C. schrieb:
> Schaumal was zur Fußnote 72 steht ;-)

Da steht "A floating-point status flag is not an object and can be set 
more than once within an expression."

Und?

> Was Gefällt Dir nicht an meinem letzten comment:

Dass es völlig egal ist, was du von C erwartest und was C deiner Ansicht 
nach tun sollte. Entscheidend ist, was der Standard definiert.

In deinem Statement wird i dreimal modifiziert. Und nun lies nochmal, 
was der Standard schreibt: "Between the previous and next sequence point 
an object shall have its stored value modified at most once by the 
evaluation of an expression."

> Spielt hier denn nich eine Reihenfolge eine Rolle? Zb eine art
> Evaluationsreihenfolge?

Es gibt Sequence Points, aber in diesem Statement ist keiner. Nur davor 
und danach, aber nicht darin.
Gast #3497801
Lesenswert?

Hallo zusammen,

int i = 1;
i += i++ + ++i;

in diesem Beispiel kommt tatsächlich IMMER 7 raus, allerdings kann das 
auf zwei Arten berechnet werden:

Auswertereihenfolge der Operatoren:
'+=' wird zuletzt ausgewertet
'+' wird als vorletztes ausgewertet und bei
i++ und ++i ist die Reihenfolge undefiniert, in jedem Fall werden beide
vor dem '+' ausgewertet. Also

1. Möglichkeit i++ wird als erstes ausgewertet:
i++ hat den Wert 1, i ist nach der Auswertung 2
++i hat dann den Wert 3, i ist ebenfalls 3
Damit wird die ganze Rechnung zu i = 3 + (1 + 3) und damit zu 7

2. Möglichkeit ++i wird als erstes ausgewertet:
++i hat den Wert 2, i ist nach der Auswertung ebenfalls 2
i++ hat dann den Wert 2, i ist danach 3
Damit wird die ganze Rechnung zu i = 3 + (2 + 2) und damit ebenfalls 7
#3497818
Lesenswert?

A. K. schrieb:
>
> Dass es völlig egal ist, was du von C erwartest und was C deiner Ansicht
> nach tun sollte. Entscheidend ist, was der Standard definiert.
>
> In deinem Statement wird i dreimal modifiziert. Und nun lies nochmal,
> was der Standard schreibt: "Between the previous and next sequence point
> an object shall have its stored value modified at most once by the
> evaluation of an expression."
>
> Wenn dir das immer noch nicht reicht, dann definiere dein eigenes
> "Bülent C", aber behaupte nicht, das wäre "Standard C".
>
>> Spielt hier denn nich eine Reihenfolge eine Rolle? Zb eine art
>> Evaluationsreihenfolge?
>
> Es gibt Sequence Points, aber in diesem Statement ist keiner. Nur davor
> und danach, aber nicht darin.
Du änderst Deinen Beitrag mehrfach in kürzester Zeit! Ist das Dein 
Standart zu debattieren?

Und außerdem gehst Du auf einen wichtigen Aspekt nicht ein und ehrlich 
gesagt habe ich auch keine Lust mehr mich mit Dir zu beschäftigen.
#3497830
Lesenswert?

Bülent C. schrieb:
> A. K. schrieb:
>> @chris: Da es sich eindeutig um "undefined behaviour" handelt,
>> darf auch
>> -9999 rauskommen. Oder ein Absturz.
>
> QUATSCH!

"Possible undefined behavior ranges from ignoring the situation 
completely with unpredictable results, to behaving during translation or 
program execution in a documented manner characteristic of the 
environment (with or without the issuance of a diagnostic message), to 
terminating a translation or execution (with the issuance of a 
diagnostic message)."

GCC ist in neueren Versionen dafür berüchtigt geworden, undefiniertes 
Verhalten kreativ zu seinen Gunsten auszulegen. Das hat schon manche 
überrascht.
Gast #3497833
Lesenswert?

'+=' wird zwar zuletzt ausgewertet. Dennoch kann der Compiler 
theoretisch eine temporäre Variable erzeugen, womit das Ergebnis auch 4 
oder 5 oder auch was ganz anderes sein kann.

gcc: (mit -Wall)
test1.c: In function ‘main’:
test1.c:6:7: warning: operation on ‘i’ may be undefined 
[-Wsequence-point]
test1.c:6:7: warning: operation on ‘i’ may be undefined 
[-Wsequence-point]

clang: (funktioniert wohl erst ab 3.3 oder sogar 3.4)
test1.c:6:11: warning: unsequenced modification and access to 'i'
      [-Wunsequenced]
    i += i++ + ++i;
      ~~  ^
1 warning generated.
(Firma: privatfrickler.de) #3497863
Lesenswert?

Hallo,

chris schrieb:
> Hallo zusammen,
>
> int i = 1;
> i += i++ + ++i;

> Auswertereihenfolge der Operatoren:

> '+' wird als vorletztes ausgewertet und bei
> i++ und ++i ist die Reihenfolge undefiniert, in jedem Fall werden beide
> vor dem '+' ausgewertet. Also

beide vor dem +? Echt? Warum denn solches? Hätte ich nicht gedacht.
Also in C++ würde

    int i = 1;
    std::cout << i++ + 1;

Die Ausgabe 2 erzeugen,
also das ++ würde natürlich nach dem + ausgewertet. Weicht C an der 
Stelle ab?
Das wäre doch sehr seltsam!

vlg
Timm

P.S. Bei mir ergibt schon das bloße Eintippen von
i += i++ + ++i; eine gelbe Unterlegung mit Warndreieck und
den Hinweis: Unsequenced modification and access to 'i'
#3497909
Lesenswert?

A. K. schrieb:
> Hier war auch schon jemand über undefiniertes Verhalten gestolpert.

In meinem ersten Job sind wir auch mal über so ein undefiniertes 
Verhalten gestossen. War ein ziemlich komplexer legacy Code eines 
Geldautomaten, Auswertung des Authorisierungscodes von der 
Authorisierungszentrale
War ungefähr so:

unsigned char[3] answer;
receive(answer);
if ((answer[i++] == '0') && (answer[i++]))
  return ok;
else
  ...

hatte in MSC 5.X einwandfrei funktioniert, beim Umstieg auf MSC 6.0 
wurde leider zweimal das erste Zeichen ausgewertet.
Der Code für Karte gesperrt war "04" Die Auswertung sah "00", das hies 
alles OK, auszahlen.

Bis die Bank es gemerkt hatte waren irgendwas zwischen 20000 und 100000 
DM weg!
Kein Witz.
Gast #3497929
Lesenswert?

Ohne alles genau durchgelesen zu haben:
1
#include <stdio.h>
2

3
int main()
4
{  int *n;
5
  int m[2][3] ={{2,5,8},{4,8,9}};
6
  n-- = *(m+1)+2;
7
  printf("%d\n", *n);
8
  n--;
9
  printf("%d\n", *n);
10
}

In dem Programm geht es nicht um Operator-Vorrang, weil *n-- = *(m+1)+2; 
funktioniert ja. Genauso wie n = *(m+1)+2; geht und anschließend 
dekrementieren.

>>Es ändert aber nichts daran, dass n-- keine Lvalue
>>ist, also nicht links von einer Zuweisung stehen darf.

Wieso lässt er das nicht durchgehen wie im obigen Beispiel bzw was ist 
der Sinn dahinter dass dies vom Standard verboten wird? Eigentlich ja 
daran nichts ungewöhnliches.
Gast #3497939
Lesenswert?

Matthias schrieb:
>>>Es ändert aber nichts daran, dass n-- keine Lvalue
>>>ist, also nicht links von einer Zuweisung stehen darf.
>
> Wieso lässt er das nicht durchgehen wie im obigen Beispiel bzw was ist
> der Sinn dahinter dass dies vom Standard verboten wird? Eigentlich ja
> daran nichts ungewöhnliches.

was soll das für einen sinn machen.

n-1 = 5;

das ist nun mal keine Zuweisung
Moderator #3497940
Lesenswert?

Hier ist ein Beispiel, wo sich zwei unterschiedliche Compiler
unterschiedlich undefiniert verhalten:
1
#include <stdio.h>
2

3
int main () {
4
  int i, j; 
5
  j = (i=1) + (i=2);
6
  printf("%d\n", j);
7
  return 0;
8
}

GCC:
1
4

Clang:
1
3

Welcher hat wohl recht?

Beide.


Udo Schmitt schrieb:
> if ((answer[i++] == '0') && (answer[i++]))
>   return ok;
> else
>   ...
>
> hatte in MSC 5.X einwandfrei funktioniert, beim Umstieg auf MSC 6.0
> wurde leider zweimal das erste Zeichen ausgewertet.

Wenn ich mich nicht täusche, ist das aber ein Fehler des Compilers (MSC
6.0) und nicht des Programmierers, denn

  "Unlike the bitwise binary & operator, the && operator guarantees
  left-to-right evaluation; there is a sequence point after the
  evaluation of the first operand."

> Bis die Bank es gemerkt hatte waren irgendwas zwischen 20000 und 100000
> DM weg!

Geld von MS zurückfordern :)
#3497942
Lesenswert?

OK, es ist ein "undefined behaviour".... gebe mich zu diesem Punkt 
geschlagen....

Warum kommt aber immer 7 raus?

Wenn ich anstelle:

  int i = 1;
  i += i++ + ++i;

dieses nehme
  int i = 1;
  i += ++i + i++;

bekomme ich immer 8 raus...

Da hier zwischen den beiden Statements unterschiedle Ergebnise geliefert 
werden, aber jeweils immer die gleichen, kann man doch die Annahme 
treffen, das es eine Reihenfolge bzw. eine Priorisierung festgelegt 
wird.
Folglich scheint erst das i++ dann ++i ausgewertet und dann zusammen 
addiert und i hinzugefügt.
Basierend auf was wird eine Reihenfolge festgelegt?
Oder will mir jemand ein "irrationales Verhalten" des compilers 
Beweisen?!
#3497954
Lesenswert?

Yalu X. schrieb:
> Geld von MS zurückfordern :)

Der Schaden hat sich meines Wissens Bank/Versicherung und mein 
Unternehmen zu gleichen Teilen geteilt, weis ich aber nicht genau.
Auf jeden Fall gab es damals ordentlich Stunk. Problem war, das war Code 
zur Authorisierung mit einer amerikanischen Kreditkartenfirma. Wenn man 
mit der testen wollte musste man
- eine funktionierende Testkarte haben
- das Testsystem in USA zum Laufen bringen (viel telefon)
- das Testsystem der Europazentrale (London) zum Laufen bringen (noch 
mehr Telefon)
- das Testsystem der Deutschlandzentrale zum Laufen bringen (...)

Und die Person, die das immer gemacht hatte und die Ansprechpartner 
kannte, war gerade ein paar Wochen weg (hatte bessern Job gefunden)

Das war alles noch im pre-Internet Zeitalter mit X25 / Datex-P

War schon spannend .-)
#3497962
Lesenswert?

Bülent C. schrieb:
> Warum kommt aber immer 7 raus?

Wenn alles rauskommen darf, dann ist 7 doch nicht falsch. Compiler sind 
nicht dazu verpflichtet, bei undefiniertem Verhalten eine Bombe zu 
zünden. Sie nicht einmal dazu verpflichtet, eine Warning zu liefern, und 
dennoch tut gcc das hier (-Wall).

> Da hier zwischen den beiden Statements unterschiedle Ergebnise geliefert
> werden, aber jeweils immer die gleichen, kann man doch die Annahme
> treffen, das es eine Reihenfolge bzw. eine Priorisierung festgelegt
> wird.

Nein.

> Basierend auf was wird eine Reihenfolge festgelegt?

Wie es sich aus der inneren Arbeitsweise des Compilers eben ergibt. Hier 
kommt immer das gleiche raus. In anderen Beispielen nicht.
Gast #3497967
Lesenswert?

Bülent C. schrieb:
> Basierend auf was wird eine Reihenfolge festgelegt?

Auf Basis vom Quellcode des GCC. Es kann sich aber in der nächsten 
Version wieder ändern. Im schlimmsten fall ist es sogar abhängig von den 
Speicheradresse der internen GCC Strukturen - ist aber auch egal. Das 
das verhalten nicht definiert ist jede Lösung richtig.
#3497973
Lesenswert?

Matthias schrieb:
> Wieso lässt er das nicht durchgehen wie im obigen Beispiel bzw was ist
> der Sinn dahinter dass dies vom Standard verboten wird? Eigentlich ja
> daran nichts ungewöhnliches.

Wieso wurde in C die Zuweisung mit = definiert, statt über := die 
Verwechslungen wie beim Klassiker "if (i = 2)" zu vermeiden? Es wurde 
vom Standard nun einmal definiert, dass n-- eine Rvalue ist und keine 
Lvalue. Und Dennis Ritchie kannst du leider nicht mehr fragen.

Besonders sinnvoll finde ich
   n-- = 0;
allerdings auch nicht wirklich.
#3498010
Lesenswert?

casud schrieb:
> Bülent C. schrieb:
>> Wenn ich anstelle: ..
>> dieses nehme
>>   int i = 1;
>>   i += ++i + i++;
>>
>> bekomme ich immer 8 raus...
>
> Hier bekomme ich zum Beispiel 7 raus und schon schnappt die Falle zu...

Was für 'ne Falle?? Das der Compiler Irrational handelt oder wie?...
Ist schon klar das es ein undefiniertes Verhalten ist, aber mit dem 
gleichen Compiler kommen bei beidem unterschiedliche Werte raus....
#3498016
Lesenswert?

Peter II schrieb:
> Bülent C. schrieb:
>> Basierend auf was wird eine Reihenfolge festgelegt?
>
> Auf Basis vom Quellcode des GCC. Es kann sich aber in der nächsten
> Version wieder ändern. Im schlimmsten fall ist es sogar abhängig von den
> Speicheradresse der internen GCC Strukturen - ist aber auch egal. Das
> das verhalten nicht definiert ist jede Lösung richtig.

Das hört sich sinnvoll an.
#3498024
Lesenswert?

Bülent C. schrieb:
> Was für 'ne Falle??

Die Falle, sich bei Code mit gemäss Standard undefiniertem Verhalten auf 
ein bestimmtes Verhalten des realen Compilers zu verlassen, "weil es 
doch schon immer so war".

So dürfte auch der Spass mit der vorhin verlinkten Totschleife bei 
vielen Compilern so ausgehen, wie der Programmierer sich das gedacht 
hatte. Wohl auch in den meisten Vorversionen von GCC. Aber irgendwann...

Es stolpern auch immer und immer wieder Leute darüber, dass sie abhängig 
von der Optimierungsstufe ein anderes Ergebnis erhalten. Das ist 
überhaupt nicht irrational, sofern das Programm formal korrekt ist.
Gast #3498259
Lesenswert?

int i;
int f(){i=1; return i;}
int g(){i=2; return i;}
i = f()+g();
=> undefined behaviuor ... ohne lange zu überlegen
kein Sequenzpunkt bei Mehrfachzuweisung an i

übrigens auch die Reihenfolge der Aufrufe f und g
sind nicht definiert. Jetzt breche ich eine weitere Diskussion
mit mirki :)

in Java ist meines Wissens Ergebnis der Mehrfachzuweisungen definiert.
Man hat sich schlicht gesagt .. mach erst präinc, dann postinc
in C hat man sich gesagt, Compiler ist frei seine
"process chunks" zu-zuschneiden. Er ist auch frei f und g Aufrufe
gleichzeitig auf multicore ablaufen zu lassen ... so what
in Java wird's wahrscheinlich erst f, dann g aufgerufen
#3498331
Lesenswert?

Martin schrieb:
> übrigens auch die Reihenfolge der Aufrufe f und g
> sind nicht definiert. Jetzt breche ich eine weitere Diskussion
> mit mirki :)

Wenn eine Reihenfolge laut Definition nicht festgelegt ist, aber 
anscheinend doch eine Reihenfolge vom Complier eingehalten wird, was ich 
ja schon bewiesen habe, dann scheint dieser nach Deiner Auffasung eine 
Willkürliche Wahl des Compilers zu sein?!
Undefiniert für den Compiler würde bedeuten, das jedesmal ein anderes 
Ergebnis rauskommen würde, tut es aber nicht beim gleichen Compiler.
#3498349
Lesenswert?

Bülent C. schrieb:
> Undefiniert für den Compiler würde bedeuten, das jedesmal ein anderes
> Ergebnis rauskommen würde, tut es aber nicht beim gleichen Compiler.

Was du schreibst würde wiederum eine Definition voraussetzen. Nämlich 
die, dass jedes Mal etwas anders heraus kommen müsse. Aber auch diese 
Definition gibt es nicht, so dass auch jedes Mal das gleiche Ergebnis 
rauskommen darf. ;-)

Ernst beiseite: Der Begriff "undefiniert" bedeutet nur, dass der 
Standard kein bestimmtes Ergebnis definiert und schlicht völlig offen 
lässt, was passiert. Unspezifiziert hiesse, dass es eine Regel gibt, die 
aber der Implementierung überlassen ist und darin offengelegt wird. 
Undefiniert heisst auch, dass nicht definiert ist ob es eine Regel gibt 
oder nicht, und dies auch niemand zu erfahren braucht.
Gast #3498359
Lesenswert?

Bülent C. schrieb:
> Wenn eine Reihenfolge laut Definition nicht festgelegt ist, aber
> anscheinend doch eine Reihenfolge vom Complier eingehalten wird, was ich
> ja schon bewiesen habe,

d.h. Du hast bewiesen dass anscheinend eine Reihenfolge eingeahlten 
wird?
In der Mathematik und Logik laufen Beweise anders ab
#3498388
Lesenswert?

Bülent C. schrieb:
> Solange Du mir nicht das Gegenteil beweist, dann ist mein Beweis gültig,
> auch wenn dieser nur auf einen Compiler Typen beschränkt ist.

Eine Behauptung wird nicht schon dadurch zum Beweis, dass sich niemand 
bemüssig fühlt, das Gegenteil zu beweisen.

Der Begriff "undefiniert" schliesst nicht aus, dass sich Programme auch 
in dem dadurch umrissenen Gebiet nach Regeln verhalten. Tatsächlich 
geschieht das sogar ziemlich häufig. Wenn du dich auf solche Regeln 
einlässt, dann programmierst du allerdings nicht in "ANSI C", sondern in 
"Bülent C".
#3498412
Lesenswert?

Bülent C. schrieb:
> Das ist doch ein Widerspruch in sich...

Nein, keineswegs.

> Kann man sich einigen auf : Im
> Standart sprec ist es undefiniert aber im Compiler exisitiert eine
> Reihenfolgen Definition?

Nein. Das wird zwar meist so sein, ist aber nicht definiert. Ausserdem 
kennst du diese Definition nicht wirklich genau, selbst wenn sie 
existiert.

Im Übrigen solltest du bedenken, dass bei der Ausseinandersetzung 
zwischen Compilern und Menschen der Compiler praktisch immer sturer ist. 
Kein Anwender ist so stur wie ein Compiler, auch wenn er sich noch so 
anstrengt. Da kannst du regalmeterweise Beschwörungen runterbeten und 
Behauptungen zu Beweisen erklären. Solange du nicht zu seinen Herren und 
Meistern gehörst, also jenen, die ihn verstehen und an ihm rumschreiben 
können, bleibt er stets der Sieger.
Gast #3498443
Lesenswert?

Bülent C. schrieb:
> Walter schrieb:
>> d.h. Du hast bewiesen dass anscheinend eine Reihenfolge eingeahlten
>> wird?
>> In der Mathematik und Logik laufen Beweise anders ab
>
> Solange Du mir nicht das Gegenteil beweist, dann ist mein Beweis gültig,
> auch wenn dieser nur auf einen Compiler Typen beschränkt ist.

dann habe ich auch "bewiesen" dass MS-Word fehlerfrei ist denn ich habe 
damit schon 2 Texte geschrieben und es hat funktioniert.
#3498451
Lesenswert?

A. K. schrieb:
> Im Übrigen solltest du bedenken, dass bei der Ausseinandersetzung
> zwischen Compilern und Menschen der Compiler praktisch immer sturer ist.
> Kein Anwender ist so stur wie ein Compiler, auch wenn er sich noch so
> anstrengt. Da kannst du regalmeterweise Beschwörungen runterbeten und
> Behauptungen zu Beweisen erklären. Solange du nicht zu seinen Herren und
> Meistern gehörst, also jenen, die ihn verstehen und an ihm rumschreiben
> können, bleibt er stets der Sieger.

Kniest Du vor Deinem Compiler nieder, weil er etwas machst was ihm nicht 
vorgegeben wurde?
#3498462
Lesenswert?

Bülent C. schrieb:
> Kniest Du vor Deinem Compiler nieder, weil er etwas machst was ihm nicht
> vorgegeben wurde?

Kommt drauf an welcher, also ob ich sein Herr und Meister bin (das ist 
freilich schon eine Weile her), oder nur sein Anwender. Wobei ich aber 
auch GCC schon mal auf die Sprünge half, als mir sein Ergebnis nicht 
passte.

Im Regelfall bleibt einem freilich keine Alternative, als vor ihm nieder 
zu knien und ihm zu folgen, wenn man zu einem Ergebnis kommen will. 
Andere Herren und Meister zu beschwören (etwa via Bugzilla) dauert meist 
zu lang.

Wie ist dein Ansatz? Ihn so lange zu verfluchen bis er dich erhöhrt?
Gast #3498490
Lesenswert?

Bülent C. schrieb:
> Das ist doch ein Widerspruch in sich...Kann man sich einigen auf : Im
> Standart sprec ist es undefiniert aber im Compiler exisitiert eine
> Reihenfolgen Definition?

im determistischen Compiler ja
wer garantiert dir das dein Compiler deterministisch ist?

Worauf du vielleicht hinaus willst ist .. implementation defined 
behaviour

es gibt
1) undefined behaviour
2) implementation defined behaviour
3) unspecified behaviour

Die letzten beiden unterscheiden sich ... (Quelle wiki)
1
The exact definition of unspecified behavior varies. In C++, it is defined as "behavior, for a well-formed program construct and correct data, that depends on the implementation."[4] Unlike implementation-defined behavior, there is no requirement for the implementation to document its behavior

int x=1;
x/0 => undefined, kann beim gleichen Compiler jedes mal anderes Ergebnis 
herauskommen

{int x; print("%d", x);} => undefined, kann beim gleichen Compiler
jedes mal anderes Ergebnis herauskommen

bei f()+g() Aufrufreihenfolge scheint es sich um "impl. defined 
behaviour"
zu handeln
#3498503
Lesenswert?

Martin schrieb:
> bei f()+g() Aufrufreihenfolge scheint es sich um "impl. defined
> behaviour" zu handeln

Nein. Implementation defined ist beispielsweise die Länge externer Namen 
jenseits der Mindestvorgabe des Standards. Das findest du irgendwo im 
Manual angegeben. Hier ist es jedoch unspecified, weil es je nach Laune 
des Compilers (Kontext, Optimierung) unterschiedlich sein kann.

Im Unterschied zu "undefined" ist aber sicher, dass du ein Ergebnis 
bekommst, dass sich aus der Addition der Return-Werte ergibt (ohne 
Überlauf).

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren