bekomme ich die Meldung:
operation on 'maincounter' may be undefined
wenn ich maincounter++ mit maincounter+1 ersetze, funktioniert es. Wieso
wird ++ nicht erkannt?
Mark schrieb:> wenn ich maincounter++ mit maincounter+1 ersetze, funktioniert es. Wieso> wird ++ nicht erkannt?
Weil es nicht das Gleiche ist.
Mark schrieb:> maincounter = (maincounter >= 250) ? 0 : maincounter++;
In Textform: Wenn maincounter grösser oder gleich 250 ist, liefere null
und weise den gelieferten Wert maincounter zu. Ansonsten liefere
maincounter, inkrementiere maincounter und weise den gelieferten Wert
maincounter zu.
EDIT:
Wenn maincounter < 250 ist, steht da:
@Be Stucki (bestucki)
>maincounter = maincounter++;>Das ist Unsinn und daher undefiniert.
Naja, in C sind ganz andere Sachen definiert. Auch das hier sollte
gültiges C sein, denn maincounter wird sich selber wieder zugewiesen und
DANACH nach einmal incrementiert. Ist zwar Käse, geht aber.
So oder so ist ein normales if() besser.
Falk B. schrieb:> Naja, in C sind ganz andere Sachen definiert. Auch das hier sollte> gültiges C sein, denn maincounter wird sich selber wieder zugewiesen und> DANACH nach einmal incrementiert.
Nein, das ist nicht definiert. Der Ausdruck kann verursachen, was er
will.
Falk B. schrieb:> @Be Stucki (bestucki)>>>maincounter = maincounter++;>>>Das ist Unsinn und daher undefiniert.>> Naja, in C sind ganz andere Sachen definiert. Auch das hier sollte> gültiges C sein,
Syntaktisch ja. Das Ergebnis der Operation ist aber undefiniert, so wie
es das in C immer ist, wenn ein Objekt mehr als einmal geschrieben wird,
ohne dass ein Sequenzpunkt dazwischen liegt.
> denn maincounter wird sich selber wieder zugewiesen und DANACH nach> einmal incrementiert.
Sagt wer?
Falk B. schrieb:> Naja, in C sind ganz andere Sachen definiert. Auch das hier sollte> gültiges C sein, denn maincounter wird sich selber wieder zugewiesen und> DANACH nach einmal incrementiert.
Ist nicht definiert. Aus dem Standard:
> The value computation of the result is sequenced before the side effect> of updating the stored value of the operand. With respect to an> indeterminately-sequenced function call, the operation of postfix ++> is a single evaluation.
Das "indeterminately-sequenced function call" ist das Wichtige dabei. Es
ist nicht definiert, wann der Wert geschrieben wird, daher ist der
gesamte Ausdruck undefiniert.
Falk B. schrieb:> @Mark (Gast)>>maincounter = (maincounter >= 250) ? 0 : maincounter++;> Sowas sollte man lassen, das ist schlechter Stil.> https://www.mikrocontroller.net/articles/Strukturierte_Programmierung_auf_Mikrocontrollern#Benennung_von_Variablen.2C_Makros.2C_Nutzung_von_Anweisungen>> Was spricht gegen ein simples> if (++maincounter >= 250) maincounter=0;
In diesem Fall wäre ein if-else besser gewesen. Ich würde aber den
?-Operator nicht grundsätzlich als schlechten Stil verteufeln. Einfache
Ausdrücke kann man damit übersichtlich in eine kurze Zeile schreiben.
Ich empfinde es übrigens als schlechten Stil, keine geschweiften
Klammern zu verwenden.
Falk B. schrieb:> if (++maincounter >= 250) maincounter=0;
C-Fans neigen gar sehr, immer alles zusammenziehen zu wollen, egal was
sie sich an Un-Lesbarkeit oder Bugs dabei einhandeln. Wahrscheinlich
kann man solches Fehlverhalten nicht abgewöhnen.
Bei mir wäre das:
++maincounter;
if (maincounter>=250) maincounter=0;
So ist es sauber, sieht auch sauber aus, liest sich einfach und ist
ohnehin vom Compiler optimierbar. Aber der TO will vermutlich nicht
biederen Quelltext schreiben, sondern Heldentaten vollbringen - egal,
wieviel Zeit es ihn bereits gekostet hat, um hier nachzufragen, weil der
Compiler ihn angeschnarrt hat und er es selber nicht gesehen hat. In
dieser Zeit hätte er es zehnmal so hinschreiben können wie ich.
W.S.
Lothar M. schrieb im Beitrag #4651358:
> Be S. schrieb:>> Das ist Unsinn> Das ja.>> und daher undefiniert.> Mitnichten.
Die Wiederholung macht es nicht richtiger.
> Es ist recht genau definert, was da in welcher Reihenfolge> passiert,
Nein! Die Reihenfolge ist undefiniert! Was überhaupt da passiert, ist
undefiniert! Das gesamte Verhalten ist undefiniert!
Lothar M. schrieb im Beitrag #4651358:
> Ergebnis: http://codepad.org/iZpIGHGO
Das ist ein mögliches Ergebnis. Die Abwesenheit von undefiniertem
Verhalten belegt das aber nicht.
W.S. schrieb:> Bei mir wäre das:> ++maincounter;> if (maincounter>=250) maincounter=0;
Das ist aber was anderes. Der TE prüft nämlich vor dem Inkrementieren
den Wert, du erst danach.
Daher also eher:
@W.S. (Gast)
>> if (++maincounter >= 250) maincounter=0;>C-Fans neigen gar sehr, immer alles zusammenziehen zu wollen, egal was>sie sich an Un-Lesbarkeit oder Bugs dabei einhandeln. Wahrscheinlich>kann man solches Fehlverhalten nicht abgewöhnen.
Quark, es war nur ein Beispiel, wie man es per if() machen kann.
>Bei mir wäre das:>++maincounter;>if (maincounter>=250) maincounter=0;
Wenn schon "schön", dann so.
1
maincounter++;
2
if(maincounter>=250){
3
maincounter=0;
4
}
So schreib ich es im Normalfall auch! Hier hab ich es halt mal nicht
gemacht. Auch ich bin ein Anhänger der "if() immer mit
Klammern"-Schreibweise.
Falk B. schrieb:> Auch ich bin ein Anhänger der "if() immer mit Klammern"-Schreibweise.
So unterschiedlich können die Geschmäcker sein. Ich bin kein besonderer
Anhänger dieser Schreibweise, dafür aber Anhänger der
"öffnende-und-schließende-Klammer-in-der-selben-Spalte"-Schreibweise.
Dementsprechend gefällt es mir so, wie du es schreibst, überhaupt nicht.
Ich finde das unübersichtlich.
@ Rolf Magnus (rmagnus)
>> Auch ich bin ein Anhänger der "if() immer mit Klammern"-Schreibweise.>So unterschiedlich können die Geschmäcker sein.
Nicht wahr ;-)
> Ich bin kein besonderer>Anhänger dieser Schreibweise, dafür aber Anhänger der>"öffnende-und-schließende-Klammer-in-der-selben-Spalte"-Schreibweise.
Also so.
1
maincounter++;
2
if(maincounter>=250)
3
{
4
maincounter=0;
5
}
Kann man machen, ist halt eine Zeile mehr, die bei längeren Funktionen
>1 Bildschirmseite ggf. etwas weniger Überblick zulassen. Aber darüber
will ich nicht philosophieren! Es ist Geschmackssache!
>Dementsprechend gefällt es mir so, wie du es schreibst, überhaupt nicht.>Ich finde das unübersichtlich.
Ich halte mich da an die Empfehlungen von iD Software. Und wenn DIE
Jungs das so machen, kann das nicht so schlecht sein ;-)
Abschnitt Spacing
http://kotaku.com/5975610/the-exceptional-beauty-of-doom-3s-source-code
ftp://ftp.idsoftware.com/idstuff/doom3/source/CodeStyleConventions.doc
Rolf M. schrieb:> Das gesamte Verhalten ist undefiniert!
Wo ist definiert, dass "i=i++" undefiniert ist?
Mal nachgesehen: im "Standard".
Weil nämlich sowohl "i =" wie auch "i++" dem "i" in der gleichen Zeile
einen neuen Wert zuweisen, ist das nicht erlaubt...
Eigentlich ist auch beim Nachdenken klar, dass das mit dem Postinkrement
und der Zuweisung schief gehen muss. Denn das Gleichheitszeichen
bedeutet ja: "zuweisen, wenn der Term rechts vom Gleichheitszeichen
ausgewertet ist" und der Posinkrement bedeutet: "Inkrementieren, wenn
die Zeile abgearbeitet ist"...
Ich hätte da sowieso so geschrieben: i>=250 ? 0:i+1;
Nochmal Glück gehabt... ;-)
Lothar M. schrieb:> der Posinkrement bedeutet: "Inkrementieren, wenn> die Zeile abgearbeitet ist"...
Nicht ganz: Er bedeutet, dass die Variable frühestens nach dem Lesen
ihres Inhalts und spätestens beim nächsten Sequence-Point (in diesem
Fall also vor Beginn der Abarbeitung der nächsten Zeile) inkrementiert
wird.
Innerhalb dieses Intervalls darf sich der Compiler einen beliebigen
Zeitpunkt für die Inkrementierung der Variable aussuchen. Sie könnte in
diesem Fall also wahlweise vor oder nach der Zuweisung geschehen,
was zu unterschiedlichen Ergebnissen führen würde.
Um die Verwirrung nicht ins Grenzenlose wachsen zu lassen, werden solche
Konstrukte einfach komplett verboten.
Lothar M. schrieb:> Ich hätte da sowieso so geschrieben: i>=250 ? 0:i+1;
Das wollte der TO vermutlich ebenfalls, nur war ihm der Unterschied
zwischen x++ und x+1 wohl nicht ganz klar.
Yalu X. schrieb:> Innerhalb dieses Intervalls darf sich der Compiler einen beliebigen> Zeitpunkt für die Inkrementierung der Variable aussuchen. Sie könnte in> diesem Fall also wahlweise vor oder nach der Zuweisung geschehen,> was zu unterschiedlichen Ergebnissen führen würde.
Das ist C mit seinen idiotischen oder nicht vorhandenen Regeln.
Es darf nichts zugewiesen werden, solange der Ausdruck rechts
nicht komplett abgearbeitet ist, Reihenfolge ist in diesem Fall
absolut unwichtig.
Es wird immer der Eingangszustand genommen und nicht irgendwelche
Zwischenergebnise.
Links = variable (momentaner Zustand und nicht irgendein beliebiges).
Rechts = variable + 1 oder variable++
Resultat = Rechts (und es ist immer variable+1).
Das kann nur in C undefined sein.
Was die Sache hier etwas interessanter gestaltet: ? ist ein sequence
point, bezogen auf die Auswertung links und rechts davon. Nützt aber
nichts, weil dahinter wie schon beschrieben in einem Zweig
i = i++;
übrig bleibt, und da ist keiner dazwischen. Anders wärs bei
i = (i++ >= 100) ? 0 : i;
auch wenn das Code zum Haare ausraufen ist.
Marc V. schrieb:> Resultat = Rechts (und es ist immer variable+1).
Nein! Das ist doch der Witz von Postincrement. Wenn man es mit
verschiedenen Variablen macht:
1
j=i++;
Dann ist j nach dieser Zeile natürlich der Wert von i VOR dem
incrementieren.
Es ist PRE increment, ohne Vergleich, da kann es auch keine race
condition geben.
Und selbst dies kann nicht undefined sein:
1
maincounter=maincounter++;
Denn bei:
1
maincounter=maincounter+1;
meckert der Compiler überhaupt nicht, obwohl kein Unterschied
besteht.
Klar, im zweiten Fall wird ein Wert zugewiesen und im ersten
Fall direkt an der Variable rumgeschraubt, aber trotzdem...
Warnung bei so etwas kann ich verstehen:
1
a[i++]=i++;
aber in den obigen zwei Fällen nicht (auch wenn alle 3 Blödsinn sind).
Marc V. schrieb:> Beim Fragezeichen habe ich den Vergleich übersehen und der kann> natürlich so oder so ausfallen, aber warum sollte folgendes auch> undefined sein:> maincounter = ++maincounter;
Das ist ebenfals undefiniert, denn ++maincounter ist äquivalent zu
maincounter+=1. Also:
1
maincounter=++maincounter;
2
maincounter=maincounter+=1;
3
maincounter=maincounter=maincounter+1;
Alles undefiniert. Merke: Sobald zwischen zwei sequence points mehr als
einmal schreibend auf eine Variable zugegriffen wird, wird undefiniertes
Verhalten erzeugt. Eine Zuweisung ist kein sequence point.
Marc V. schrieb:> Und selbst dies kann nicht undefined sein:> maincounter = maincounter++;> Denn bei:> maincounter = maincounter+1;> meckert der Compiler überhaupt nicht, obwohl kein Unterschied besteht.
Natürlich besteht ein Unterschied. Beim Ersten wird zwei Mal in
undefinierter Reihenfolge schreibend auf maincounter zugegriffen. Beim
Zweiten wird ein Wert berechnet und zugewiesen, also nur ein
Schreibzugriff.
Be S. schrieb:> Merke: Sobald zwischen zwei sequence points mehr als> einmal schreibend auf eine Variable zugegriffen wird, wird undefiniertes> Verhalten erzeugt.
Alternativ auch, wenn zwischen zwei Sequenzpunkten die Variable
geschrieben wird und auch gelesen, ohne dass dieser Lesezugriff dazu
dient, den Wert für den Schreibzugriff zu ermitteln.
Beispiel:
1
x=variable*variable++;
Auch das ist undefiniert, da variable per Operator ++ beschrieben wird,
aber links von der Multiplikation zu einem anderen Zweck als für den
Operator++ auch gelesen wird.
Marc V. schrieb:> Und selbst dies kann nicht undefined sein:> maincounter = maincounter++;> Denn bei:> maincounter = maincounter+1;> meckert der Compiler überhaupt nicht, obwohl kein Unterschied> besteht.>> Klar, im zweiten Fall wird ein Wert zugewiesen und im ersten> Fall direkt an der Variable rumgeschraubt, aber trotzdem...
Nein. Im zweiten Fall wird zugewiesen und "direkt an der Variable
rumgeschraubt".
Also lange Rede, kurzer Sinn. Man sollte mit den C-typischen Stunts x++
etc. eher sparsam umgehen und diese Sachen lieber eindeutig und leicht
lesbar in getrennte Anweisungen schreiben.
Be S. schrieb:> Natürlich besteht ein Unterschied. Beim Ersten wird zwei Mal in> undefinierter Reihenfolge schreibend auf maincounter zugegriffen. Beim> Zweiten wird ein Wert berechnet und zugewiesen, also nur ein> Schreibzugriff.Marc V. schrieb:> Klar, im zweiten Fall wird ein Wert zugewiesen und im ersten> Fall direkt an der Variable rumgeschraubt, aber trotzdem...
Das habe ich doch auch geschrieben, oder ?
Und die Reihenfolge ist gerade in diesem Fall absolut unwichtig.
Es muss auf jeden Fall zuerst {mainconter = maincounter} ausgeführt
werden und danach Rechts erhöht werden.
Absolut kein Unterschied und vor allem kein undefiniertes Resultat.
Dieser Thread müßte eigentlich als Link in das C-Tutorial aufgenommen
werden. Warum? Um die Leute vor dem zu warnen, was sie sich aufhalsen
wollen.
MfG Paul
Marc V. schrieb:> Es muss auf jeden Fall zuerst {mainconter = maincounter} ausgeführt> werden und danach Rechts erhöht werden.
Der Standard sieht das aber anders und nur der zählt.
Marc V. schrieb:> Absolut kein Unterschied und vor allem kein undefiniertes Resultat.
Wenn das so ist, dann erkläre mir bitte folgendes Verhalten:
@ Paul Baumann (paul_baumann)
>Dieser Thread müßte eigentlich als Link in das C-Tutorial aufgenommen>werden.
Das kannst du doch machen.
> Warum? Um die Leute vor dem zu warnen, was sie sich aufhalsen>wollen.
In jedem PRAXISNAHEN C-Kurs wird vor solchen Sachen gewarnt und jeder
vernünftige Mensch wird davon auch die Finger lassen. C ist nicht
perfekt, aber nun mal ein weit verbreiteter Standard.
Falk B. schrieb:> Man sollte mit den C-typischen Stunts x++> etc. eher sparsam umgehen und diese Sachen lieber eindeutig und leicht> lesbar in getrennte Anweisungen schreiben.
Finde ich nicht. Man sollte ein bisschen nachdenken. Was soll x=x++
machen? x um eins erhöhen? Dann schreibt man x++. Sonst fällt mir keine
sinnvolle Anweisung ein, die man mit dem Ausdruck meinen könnte.
x=x++ ist in C einfach nicht definiert. Wenn das Programm mit der
Anweisung die dritte Wurzel aus x zieht und danach das Universum
zerstört, ist das absolut standardgemäß (allerdings muss ich zugeben,
dass ich nicht weiß, ob der Standard nicht an anderer Stelle die
Zerstörung des Universums verbietet :D).
Es steht jedem frei, eine neue Programmiersprache zu entwickeln, in der
das Ergebnis von x=x++ und zum Beispiel y=x/0 genau definiert ist. Eine
solche Sprache ist C aber eben nicht.
Nebenbei gesagt, habe ich auch nichts gegen sowas wie
x=x<Schwellwert?-1:1;
Das ist kurz und eindeutig.
Rolf M. schrieb:>> Klar, im zweiten Fall wird ein Wert zugewiesen und im ersten>> Fall direkt an der Variable rumgeschraubt, aber trotzdem...>> Nein. Im zweiten Fall wird zugewiesen und "direkt an der Variable> rumgeschraubt".
Wie das ?
Zuweisung ist "=".
Bei
1
maincounter+1;
wird der maincounter nur gelesen.
und mit:
1
maincounter=
wird der neue Wert zugewiesen.
Da wird zwischendurch nichts an der Variable verändert.
@Dussel (Gast)
>> Man sollte mit den C-typischen Stunts x++>> etc. eher sparsam umgehen und diese Sachen lieber eindeutig und leicht>> lesbar in getrennte Anweisungen schreiben.>Finde ich nicht. Man sollte ein bisschen nachdenken.
Darum geht es gar nicht. Quelltext soll kein Logikrätsel sein sondern
möglicht gut und einfach lesbar bzw. zu verstehen.
> Was soll x=x++>machen? x um eins erhöhen? Dann schreibt man x++. Sonst fällt mir keine>sinnvolle Anweisung ein, die man mit dem Ausdruck meinen könnte.
Darum geht es gar nicht.
>Nebenbei gesagt, habe ich auch nichts gegen sowas wie>x=x<Schwellwert?-1:1;>Das ist kurz und eindeutig.
Für so einen Müll gehört der Verursacher geteert und gefedert!!!
Das ist autistische Hackerscheiße!
Be S. schrieb:> Wenn das so ist, dann erkläre mir bitte folgendes Verhalten:
Wieso ich ?
Habe ich GCC geschrieben ?
Bin ich für dieses Verhalten verantwortlich ?
Was ist an dieser Zuweisung unklar (ausser, dass es Blödsinn ist) ?
1
x=x++;
Was kann da falsch gerechnet werden und undefiniert sein ?
Wie man auch rechnet - zuerst rechts, dann links, dann wieder rechts
oder andersrum - es ergibt immer x+1.
Dass es beim GCC nicht so abläuft wie es ablaufen soll, ist bestimmt
nicht mein Fehler.
Dussel schrieb:> x=x++ ist in C einfach nicht definiert. Wenn das Programm mit der> Anweisung die dritte Wurzel aus x zieht und danach das Universum> zerstört, ist das absolut standardgemäß (allerdings muss ich zugeben,> dass ich nicht weiß, ob der Standard nicht an anderer Stelle die> Zerstörung des Universums verbietet :D).
Der Standard sagt dazu:
> undefined behavior> behavior, upon use of a nonportable or erroneous program construct or> of erroneous data, for which this International Standard imposes no> requirements> NOTE 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).
Also: Entweder wird die Sache mit unvorhersehbarem Resultat ignoriert,
verhält sich nach Dokumentation oder das Programm wird beendet. Du
müsstest also in der Compilerdokumentation nachsehen, ob das Universum
möglicherweise zerstört wird oder nicht.
Marc V. schrieb:> Dass es beim GCC nicht so abläuft wie es ablaufen soll, ist bestimmt> nicht mein Fehler.
Es läuft so ab, wie es soll. Lese und verstehe obige Beiträge und den
Standard. Nur weil du denkst, es sei so wie du denkst, heisst das noch
lange nicht, dass es auch wirklich so ist.
Falk B. schrieb:> Für so einen Müll gehört der Verursacher geteert und gefedert!!!> Das ist autistische Hackerscheiße!
Ok, ich hatte dich zwischenzeitlich wieder als etwas besser
eingeschätzt, aber damit hast du dich dann doch wieder als unfähiger
Idiot zu erkennen gegeben.
Schade.
Falk B. schrieb:> Ich halte mich da an die Empfehlungen von iD Software. Und wenn DIE> Jungs das so machen, kann das nicht so schlecht sein ;-)
Das ist Dressur, also es genau so machen wie man es irgend wann mal
eingetrichtert bekommen hat.
OK, es kommt in diesem Falle ja nichts direkt Falsches dabei heraus.
Trotzdem ist es schlichtweg logischer,
if (bedingung) Statement;
zu schreiben. Und wenn das Statement eben nur ein einfaches Statement
ist, dann gehört darum keine Block-Klammer, denn es ist ja kein Block,
den man zusammenfassen müßte.
Auch überflüssiger Zinnober, der zwar nicht zu Fehlern führt, aber
dennoch eben überflüssig ist, ist ÜBERFLÜSSIG - und irgendwann
verwirrend. Das gilt auch für die üble Angewohnheit, Block-Eröffnungen
auf das davorliegende Zeilenende zu verfrachten. Jaja, auch wenn ganz
viele Leute das genau so machen, eben weil sie es andressiert bekommen
haben und sich seitdem keinen eigenen Gedanken darüber gemacht haben.
Kurzum, die Schreibweise, wo Blockeröffnung und Blockende in der
gleichen Spalte stehen, ist sauberer, da sie dem menschlichen Leser das
visuelle Erfassen der Struktur erleichtern. In diesem Falle
if (bedingung)
{ ...
...
}
Dem Compiler hingegen ist das alles wurscht.
W.S.
Be S. schrieb:> Es läuft so ab, wie es soll. Lese und verstehe obige Beiträge und den> Standard. Nur weil du denkst, es sei so wie du denkst, heisst das noch> lange nicht, dass es auch wirklich so ist.
Wenn es um verstehen geht, wollte ich dir gerade dasselbe empfehlen.
Wenn es um Standard geht, ist es eine ganz andere Sache - da kann
auch drin stehen, dass a + 3 immer 9 ergibt, unabhängig vom Wert der
Variable a.
Wenn ich diese Sprache benutzen will, muss ich damit leben.
Genauso ist es mit a = a++;
Ob das aber einen Sinn ergibt, ist wiederum eine ganz andere Sache.
Es gab mal (früher) eine Story wie und warum C überhaupt entstanden
ist. Ich glaube immer mehr, dass diese wahr ist...
W.S. schrieb:> Kurzum, die Schreibweise, wo Blockeröffnung und Blockende in der> gleichen Spalte stehen, ist sauberer, da sie dem menschlichen Leser das> visuelle Erfassen der Struktur erleichtern.
Selbstverständlich ist es so logischer und vor allem übersichtlicher.
Aber irgendwie sieht es nach Anfänger aus und da alle die in C
programmieren (meistens erfolglos) sich für grosse Experten halten,
ist es verpönt.
Marc V. schrieb:> Wenn es um verstehen geht, wollte ich dir gerade dasselbe empfehlen.
Ich verstehe deine Einwände, dass man die Operation in solch simplen
Fällen auch hätte definieren können. Macht aber keinen Sinn, denn dann
hätte man konsequenterweise auch
1
x=x+++++x;
und
1
y[x++]=++x;
definieren müssen.
Marc V. schrieb:> Und selbst dies kann nicht undefined sein:> maincounter = maincounter++;> Denn bei:> maincounter = maincounter+1;> meckert der Compiler überhaupt nicht, obwohl kein Unterschied besteht.Marc V. schrieb:> Absolut kein Unterschied und vor allem kein undefiniertes Resultat.
Diese beiden Aussagen lassen darauf schliessen, dass das Resultat nicht
undefiniert sei und beide Beispiel äquivalent sein würden. Dies ist aber
nicht korrekt, deswegen meine Einwände.
Be S. schrieb:> maincounter = ++maincounter;> maincounter = maincounter += 1;> maincounter = maincounter = maincounter + 1;>> Alles undefiniert.
In diesem Fall bin ich mir in C99 nicht so sicher.
Das C99 Rationale drückt sich nämlich in 6.5.16 ein wenig anders aus:
"The storage assignment need not take place until the next sequence
point. As a consequence, a straightforward syntactic test for ambiguous
expressions can be stated. Some definitions: A side effect is a storage
to any data object [...]. An ambiguous expression is one whose value
depends upon the order in which side effects are evaluated. [...]"
`whose value depends upon the order in which side effects are
evaluated´. Es ist also nicht entscheidend, wie oft geschrieben wird,
sondern ob sich durch eine andere Reihenfolge etwas ändern kann. Was
hier nicht der Fall ist.
"A sequenced expression is one whose major operator defines a sequence
point: comma, &&, ||, or conditional operator; an unsequenced expression
is any other. We can then say that an unsequenced expression may be
ambiguous [..] if more than one operand contains an lvalue referencing
the same object and one or more operands specify a side effect to that
object."
`may be ambiguous´. Kann zweideutig sein, muss aber nicht.
(Weggelassen habe ich Aussagen über bestimmte Funktionsaufrufe und
volatile Zugriffe)
Aus (1)
> Sobald zwischen zwei sequence points mehr als> einmal schreibend auf eine Variable zugegriffen wird, wird undefiniertes> Verhalten erzeugt.
wird diesem Text zufolge also (2)
> Sobald zwischen zwei sequence points mehr als> einmal schreibend auf eine Variable zugegriffen wird, kann undefiniertes> Verhalten erzeugt werden.
PS: Dass man so einen Stuss nicht schreiben sollte ist klar. Also dass
man sich an (1) halten sollte, auch wenn formal (2) korrekt ist.
Be S. schrieb:> müsstest also in der Compilerdokumentation nachsehen, ob das Universum> möglicherweise zerstört wird oder nicht.
Das sollte bei "implementation defined" helfen, hilft vielleicht auch
bei "unspecified", nicht aber bei "undefined".
@ W.S. (Gast)
>> Ich halte mich da an die Empfehlungen von iD Software. Und wenn DIE>> Jungs das so machen, kann das nicht so schlecht sein ;-)>Das ist Dressur, also es genau so machen wie man es irgend wann mal>eingetrichtert bekommen hat.
Blödsinn^3! Die Jungs von ID Software haben wir kaum was eingetrichtert.
Sie haben IHRE Sicht der Dinge dragestellt, ich hab sie angesehen und
drüber nachgedacht und am Ende fand ich fast alles logisch, schlüssig
und sinnvoll!
>Trotzdem ist es schlichtweg logischer,>if (bedingung) Statement;>zu schreiben. Und wenn das Statement eben nur ein einfaches Statement>ist, dann gehört darum keine Block-Klammer, denn es ist ja kein Block,>den man zusammenfassen müßte.
NEIN!!! Warum das so ist, steht in den Links!
>Auch überflüssiger Zinnober, der zwar nicht zu Fehlern führt, aber>dennoch eben überflüssig ist, ist ÜBERFLÜSSIG - und irgendwann>verwirrend.
Du hast es nicht verstanden.
> Das gilt auch für die üble Angewohnheit, Block-Eröffnungen>auf das davorliegende Zeilenende zu verfrachten.
Auch das wurde begründet!!!
>Jaja, auch wenn ganz>viele Leute das genau so machen, eben weil sie es andressiert bekommen
Quark.
>haben und sich seitdem keinen eigenen Gedanken darüber gemacht haben.
Das GEGENTEIL ist der Fall!
>Kurzum, die Schreibweise, wo Blockeröffnung und Blockende in der>gleichen Spalte stehen, ist sauberer,
Hast du dein Pascal-Martyrium noch nicht überwunden ? ;-)
> da sie dem menschlichen Leser das>visuelle Erfassen der Struktur erleichtern.
Die andere Schreibweise auch, dennjedes if() braucht eine schließende
Klammer, die öffnende steht am Zeilenende.
>Dem Compiler hingegen ist das alles wurscht.
Darum geht es keine Sekunde. Dann dann könnte man gleich alles in eine
Zeile schreiben. Thema verfehlt!
@Be Stucki (bestucki)
>> Wenn es um verstehen geht, wollte ich dir gerade dasselbe empfehlen.>Ich verstehe deine Einwände, dass man die Operation in solch simplen>Fällen auch hätte definieren können. Macht aber keinen Sinn, denn dann>hätte man konsequenterweise auch>x = x++ + ++x;>und>y[x++] = ++x;>definieren müssen.
Eben. Die Philosophie von C, aktive (schreibende) Operationen mit
logischen Ausdrücken zu vermischen ist so oder so nicht ganz koscher.
Das sollte man SEHR zurückhaltend nutzen. Wenn man erst ne Minute über
einen Ausdruck nachdenken oder gar die Operatorenreihenfolge im Buch
nachschlagen muss, ist es meist zu komplex!
@A. K. (prx)
>`may be ambiguous´. Kann zweideutig sein, muss aber nicht.>(Weggelassen habe ich Aussagen über bestimmte Funktionsaufrufe und>volatile Zugriffe)
Ob es einer Programmiersprach gut bekommt, wenn sich deren
Definition/Standard mehr und mehr wie ein juristisches Machwerk lies?
Was verliert man denn, wenn man diese logischen Spitzfindigkeiten
einfach verbietet?
KISS!!
Falk B. schrieb:>Ob es einer Programmiersprach gut bekommt, wenn sich deren> Definition/Standard mehr und mehr wie ein juristisches Machwerk lies?
K&R liess einiges in der Schwebe, was der Sprache nicht gut tat.
> Was verliert man denn, wenn man diese logischen Spitzfindigkeiten> einfach verbietet?
Der zitierte Text stammt nicht einmal aus dem Standard selbst, sondern
aus den Erklärungen dazu. ;-)
> KISS!!
Ist der Fall, denn im Grunde ist es wirklich einfach:
Verboten ist Zweideutigkeit im Ergebnis. Der Rest folgt daraus.
Marc V. schrieb:> Rolf M. schrieb:>>> Klar, im zweiten Fall wird ein Wert zugewiesen und im ersten>>> Fall direkt an der Variable rumgeschraubt, aber trotzdem...>>>> Nein. Im zweiten Fall wird zugewiesen und "direkt an der Variable>> rumgeschraubt".>> Wie das ?
Hab mich verschrieben. Ich meinte den ersten Fall, nicht den zweiten,
also
> maincounter = maincounter++;Falk B. schrieb:>> Was soll x=x++>>machen? x um eins erhöhen? Dann schreibt man x++. Sonst fällt mir keine>>sinnvolle Anweisung ein, die man mit dem Ausdruck meinen könnte.>> Darum geht es gar nicht.
Worum dann? Hier beschweren sich Leute, dass es unsinnige Ausdrücke
gibt, die in C undefiniert sind.
Marc V. schrieb:> Was ist an dieser Zuweisung unklar (ausser, dass es Blödsinn ist) ? x => x++;>> Was kann da falsch gerechnet werden und undefiniert sein ?
"Falsch gerechnet" werden kann da quasi per Definition nicht, denn
undefiniertes Verhalten heißt, dass jedes beliebige Ergebnis richtig
ist.
> Wie man auch rechnet - zuerst rechts, dann links, dann wieder rechts> oder andersrum - es ergibt immer x+1.
Es kann auch eine "trap" ergeben, wenn der Prozessor das x++ und das x =
... paralellisiert und dann einen Konflikt finden und das Programm
terminiert. Das ganze wurde ja nicht für undefiniert erklärt, weil man
keinen Bock hatte, es zu definieren, sondern um dem Compiler die Arbeit
zu erleichtern. Man muss dabei auch im Hinterkopf behalten, dass C in
den 70ern entstanden ist, als Compiler noch nicht so hochkomplex waren
wie heute und auch auf Rechnern mit ein paar kB RAM laufen mussten. Der
Optimizer oder auch der nicht optimierende Compiler muss sich zwischen
zwei Sequenzpunkten nicht darum kümmern, ob es einen Sinn ergibt, wenn
Sachen parallelisiert oder umsortiert werden oder was auch immer
rauskommt.
> Dass es beim GCC nicht so abläuft wie es ablaufen soll, ist bestimmt> nicht mein Fehler.
Es läuft so ab, wie es ablaufen soll. Dein Fehler ist, dass du falsche
Erwartungen an das Ergebnis hast.
Marc V. schrieb:> und y[x++] = ++x;>> definieren müssen.>> Selbst das muss nicht undefiniert sein, (obwohl es Blödsinn ist),> weil Rechts ein PRE increment steht, also ist das Resultat:> x = 5;> y[x++] = ++x;>> 1: y[x++] = 6;> 2: y[6] = 6;> 3: x = 7;
Damit legst du an einigen Stellen eine bestimmte Reihenfolge fest, wo
man in C bewusst dem Compiler die Freiheit gelassen hat. Ich verstehe
auch nicht das Problem. Welchen Vorteil hat man denn, wenn alle
blödsinnigen (wie du selbst schreibst) Konstrukte genau definiert sind?
A. K. schrieb:> In diesem Fall bin ich mir in C99 nicht so sicher.> `whose value depends upon the order in which side effects are> evaluated´. Es ist also nicht entscheidend, wie oft geschrieben wird,> sondern ob sich durch eine andere Reihenfolge etwas ändern kann. Was> hier nicht der Fall ist.
Entscheiden dafür, ob es eine "ambiguous expression" ist. Die Rationale
ist auch nicht normativ.
Normativ ist in C99 das hier (§6.5 "Expressions"):
"Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be read only to determine the value
to be stored."
Und das ist genau das, was hier schon geschrieben wurde, und es gilt
ohne Ausnahme. Dazu sind übrigens auch Beispiele angegeben:
"This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;"
Rolf M. schrieb:> Damit legst du an einigen Stellen eine bestimmte Reihenfolge fest, wo> man in C bewusst dem Compiler die Freiheit gelassen hat. Ich verstehe> auch nicht das Problem. Welchen Vorteil hat man denn, wenn alle> blödsinnigen (wie du selbst schreibst) Konstrukte genau definiert sind?
Gar keinen, natürlich.
Aber das sind nicht die Begrenzungen der Sprache, es ist der
Optimizer. Warum ein Ausdruck, der sich ohne Probleme parsen und
ausführen lässt, undefiniertes Ergebnis liefern soll, ist für mich
nur schwer oder überhaupt nicht zu verstehen.
Hat natürlich nichts damit zu tun, ob ein Ausdruck Sinn ergibt
oder nicht.
Wie schon geshrieben:
A. K. schrieb:> PS: Dass man so einen Stuss nicht schreiben sollte ist klar.
Nur weil man sich ins Knie schießen könnte, muß man es doch nicht tun.
Man darf alles auch so schreiben, daß man es morgen noc versteht.
Der Compiler hat gewarnt, er kann auch dazu gebracht werden dafür Fehler
zu werfen, was braucht man mehr. Solange man noch Warnungen hat, hat man
sich nicht klar genug ausgedrückt. Also nacharbeiten!
Marc V. schrieb:> Aber das sind nicht die Begrenzungen der Sprache, es ist der> Optimizer. Warum ein Ausdruck, der sich ohne Probleme parsen und> ausführen lässt, undefiniertes Ergebnis liefern soll, ist für mich> nur schwer oder überhaupt nicht zu verstehen.>> Hat natürlich nichts damit zu tun, ob ein Ausdruck Sinn ergibt> oder nicht.
Es würde nicht bei so einfachen Dingen wie x = x++ bleiben, sondern es
müssten alle Abartigkeiten spezifiziert werden. Das würde werder ein
Mehrgewinn für den Sprachstandard bedeuten, noch für in der Sprache
geschriebene Programme, noch für Compiler welche die Sprache
implementieren.
Der tiefere Grund ist aber folgender: C beschreibt das Verhalten einer
abstrakten Maschine. Wenn man sich nun z.B. auf den Wert einer
Variablen X bezieht, dann beziehnt man sich also auf den Zustand der
abstrakten Maschine. Der Standard legt nun fest, zu welchen Zeitpunkten
die reale Maschine, welche ein C-Programm ausführt, mit dem Zustand der
abstrakten, durch den Standard beschriebenen Maschine übereinzustimmen
hat. Das sind die bekannten Sequence-Points, und die sind nun mal so
festgelegt, dass x = x++ eben nicht definiert ist, weil 2x auf x
geschrieben wird.
Falls das mit der abstrakten Maschine zu abstrakt ist, kannst du mal der
konkreten Frage nachgehen, warum wohl
LD R26, X+
auf der konkrete AVR-Architektur nicht definiert ist :-)
Johann L. schrieb:>> Hat natürlich nichts damit zu tun, ob ein Ausdruck Sinn ergibt>> oder nicht.>> Es würde nicht bei so einfachen Dingen wie x = x++ bleiben, sondern es> müssten alle Abartigkeiten spezifiziert werden.
Ich denke auch, dass das ein wesentlicher Punkt ist. Man sagt einfach
mit einer kurzen Regel, dass solche Sachen alle undefiniert sind, statt
tausend Regeln bauen zu müssen, damit jeder einzelne Fall auch sauber
abgedeckt ist. Das hält auch die Sprachdefinition einfach.
Johann L. schrieb:> Falls das mit der abstrakten Maschine zu abstrakt ist, kannst du mal der
Es ist mir nicht zu abstrakt, danke der Nachfrage.
> konkreten Frage nachgehen, warum wohl> LD R26, X+> auf der konkrete AVR-Architektur nicht definiert ist :-)
Und
1
ldr26,X+
ist definiert, nur das Resultat ist nicht definiert ;-)
Was nicht weiter verwunderlich ist, denn wohin X auch zeigt und
welches register zuerst geladen wird, ob xl oder xh ist egal - X
zeigt nicht mehr dort, wo er vorhin gezeigt hat.
Insofern ist das Resultat undefiniert - es wird nicht der Wert aus
der ursprünglichen Adresse geladen und X wird zum Schluss auch
nicht X+1 sein.
A. K. schrieb:> Aus (1)>>> Sobald zwischen zwei sequence points mehr als>> einmal schreibend auf eine Variable zugegriffen wird, wird undefiniertes>> Verhalten erzeugt.>> wird diesem Text zufolge also (2)>>> Sobald zwischen zwei sequence points mehr als>> einmal schreibend auf eine Variable zugegriffen wird, kann undefiniertes>> Verhalten erzeugt werden.
Dieser Thread erklärt das ganz gut:
http://stackoverflow.com/questions/13714246/assignment-and-sequence-points-how-is-this-ambiguousMarc V. schrieb:> Warum ein Ausdruck, der sich ohne Probleme parsen und> ausführen lässt, undefiniertes Ergebnis liefern soll, ist für mich> nur schwer oder überhaupt nicht zu verstehen.
Weil der Compiler das nicht zu 100% prüfen kann (Zeiger, Casts,
verschiedene Sourcen etc.). Also überlässt man diese Verantwortung dem
Programmierer.
Mark schrieb:> wenn ich maincounter++ mit maincounter+1 ersetze, funktioniert es. Wieso> wird ++ nicht erkannt?
Nimm einfach die Bedingung raus und dann steht da.
1
maincounter=maincounter++;
Das meckert der Compiler völlig zu recht an.
Es ist nicht definiert, welche der beiden Zuweisungen zuerst erfolgt.
Erfolgt die rechte zuerst, bleibt maincounter unverändert.
1
// erst rechts:
2
temp=maincounter;
3
maincounter=maincounter+1;// post increment
4
// dann links:
5
maincounter=temp;
Erlaubt ist dagegen:
1
maincounter=(maincounter++>=250)?0:maincounter;
Das ? ist nämlich ein sequence point und damit erfolgt die rechte
Zuweisung immer zuerst.
Peter D. schrieb:> Es ist nicht definiert, welche der beiden Zuweisungen zuerst erfolgt.> Erfolgt die rechte zuerst, bleibt maincounter unverändert.// erst> rechts:> temp = maincounter;> maincounter = maincounter + 1; // post increment> // dann links:> maincounter = temp;
Mit optimieren ?
Warum Zwischenregister Links ?
avr schrieb:> Wie wärs wenn du es wenigstens mal versuchst zu verstehen? Ich übersetze> dir mal den C-Code von Peter nach Assembler falls das hilft.
Wie wäre es wenn du dich mal ein bisschen über optimieren
informierst ?
Das, was du so unglücklich zu übersetzen versucht hast, braucht
2 Bytes, 2 Takte und einen Register mehr als das, was ich gepostet
habe.
Was bringt dich zu der Annahme, dass der Compiler die längere und
langsamere Variante wählen wird ?
Marc V. schrieb:> avr schrieb:>> Wie wärs wenn du es wenigstens mal versuchst zu verstehen? Ich übersetze>> dir mal den C-Code von Peter nach Assembler falls das hilft.>> Wie wäre es wenn du dich mal ein bisschen über optimieren> informierst ?> Das, was du so unglücklich zu übersetzen versucht hast, braucht> 2 Bytes, 2 Takte und einen Register mehr als das, was ich gepostet> habe.> Was bringt dich zu der Annahme, dass der Compiler die längere und> langsamere Variante wählen wird ?
Vielleicht die Tatsache, daß y und x nicht das Gleiche sind?
Wer das Problem nicht verstanden hat, tut sich auch mit dessen Lösung
schwer.
Carl D. schrieb:> Wer das Problem nicht verstanden hat, tut sich auch mit dessen Lösung> schwer.
Genau.
Warum meldest du dich dann überhaupt zu Wort ?
Nicht die Sprache ist das Problem, sondern der Optimizer.
Damit der immer optimal arbeitet, werden solche Situationen und
deren Ergebnisse immer als undefiniert bezeichnet, soll heissen:
Es kann gut gehen, genauso aber kann es in die Hose gehen.
Aber solche Experten wie du und dein Vorredner (avr-Gast) sind
weit davon entfernt, dies auch nur ansatzweise zu verstehen.
Marc V. schrieb:> Wie wäre es wenn du dich mal ein bisschen über optimieren> informierst ?
Du bist genau so weit wie vorher: Bockig und nicht gewillt etwas zu
verstehen.
-Der AVR-Core ist bei weitem nicht die einzige Zielplattform für
C-Compiler. Ein C-Compiler muss die Plattform nicht einmal kennen.
-Optimizer können sich durchaus irren und das kommt auch immer wieder
vor.
-Nur weil du beim AVR die kürzere Variante zufällig dein gewünschtes
Ergebnis hevorbringt, ist das sicherlich nicht auf allen Architekturen
so => undefined behaviour
Abgesehen davon: Wie kommt man eigentlich darauf aus kürzerem
Assemblercode darauf zu schließen, wie der Compiler Code zu
interpretieren hat? Der Assemblercode kommt erst am Ende, da hat der
Compiler sich schon entschieden. Und wenn er sich für die andere
Variante entschieden hat, dann wird die auch so umgesetzt. Und dann wird
aus der "langen" Variante durch den Optimizer plötzlich was viel
kürzeres. Nämlich gar nichts, weil dieser merkt, dass der Code nichts
macht.
Be S. schrieb:> Ich verstehe deine Einwände, dass man die Operation in solch simplen> Fällen auch hätte definieren können. Macht aber keinen Sinn, denn dann> hätte man konsequenterweise auchx = x++ + ++x;undy[x++] = ++x;definieren> müssen.
Deswegen, und wegen dem Rest vom Thread, wurde in Swift 3 Pre- und
Postincrement abgeschafft.
Verwirrt mehr als es nutzt, zumal es das bekannte for (int i=0;i<10;i++)
auch nicht mehr gibt.
Marc V. schrieb:> Aber solche Experten wie du und dein Vorredner (avr-Gast) sind> weit davon entfernt, dies auch nur ansatzweise zu verstehen.
Ein Geisterfahrer? Tausende!
Fritz G. schrieb:> Deswegen, und wegen dem Rest vom Thread, wurde in Swift 3 Pre- und> Postincrement abgeschafft
Nur weil einer Beratungsresistent ist? Die Reihenfolge ist eben nicht
definiert. So schwer kann das doch nicht sein. In Java wurde auch die
Operatorüberladung abgeschafft. Einen sinvollen Grund dafür kenne ich
bis heute nicht.
avr schrieb:> Nur weil einer Beratungsresistent ist?
Du willst mich beraten ?
LOL.
avr schrieb:> In Java wurde auch die> Operatorüberladung abgeschafft. Einen sinvollen Grund dafür kenne ich> bis heute nicht.
Eben.
Du kennst den Grund nicht.
Marc V. schrieb:> Was bringt dich zu der Annahme, dass der Compiler die längere und> langsamere Variante wählen wird ?
Und was bringt dich zu der Annahme, die kürzere Variante wäre
besser/korrekter/schöner [1] als die längere?
[1] nichtzutreffendes streichen
Das ist doch die Crux der ganzen Diskussion. Der C-Ausdruck x = x++ kann
ganz legal auf zwei verschiedene Weisen interpretiert werden, die aber
dummerweise verschiedene Resultate liefern. Und zwar deswegen, weil der
Inkrement-Operator selber bereits eine Zuweisung an x vornimmt und es in
C keine Regel gibt in welcher Reihenfolge die Zuweisungen ausgeführt
werden wenn sich kein Sequenzpunkt dazwischen befindet.
Deswegen sagt der C-Standard "das Verhalten ist undefiniert" und jeder
vernünftige Programmierer wird einen solchen Ausdruck nicht verwenden.
Und zwar deswegen, weil "vernünftig" einschließt, daß man nur Programme
mit wohldefiniertem Verhalten schreibt. Um so mehr als
1. der Ausdruck sowieso keinen Sinn ergibt [2] und
2. jeder aktuelle Compiler eine Warnung dafür ausspuckt
Mir ist vollkommen schleierhaft, welchen weiteren Diskussionsbedarf es
an dieser Stelle geben könnte.
[2] nehmen wir mal für einen Augenblick an, der Compiler befolgt deine
Interpretation "erst die rechte Seiten komplett auswerten, inklusive
aller Nebeneffekte und dann erst die Zuweisung machen" - dann steht da
am Ende das Äquivalent von
tmp <- x (Postfix-Inkrement liefert den alten Wert, also merken)
x <- x + 1 (Inkrement-Operatur inkl. Nebeffekt)
x <- tmp (Zuweisung)
also ein teures NOP. Soll das ernsthaft deine "Lösung" sein?
Marc V. schrieb:> avr schrieb:>> In Java wurde auch die>> Operatorüberladung abgeschafft. Einen sinvollen Grund dafür kenne ich>> bis heute nicht.>> Eben.> Du kennst den Grund nicht.
1. du hast das "sinnvoll" unterschlagen
2. der Grund ist IMHO daß die Zielgruppe von Java all jene
"Programmierer" sind, die ihre Lobotomie schon bekommen haben. Über die
Sinnhaftigkeit kann man natürlich immer noch streiten ...
Wie man beim Design einer von Grund auf neuen Programmiersprache, die im
Gegensatz zu C++ [1] keinerlei Zwängen zur Rückwärtskompatibilität [2]
unterlegen ist, derart verkacken kann, wird mir ewig ein Rätsel bleiben.
[1] dem mehr oder weniger offiziellen #1 Vorgänger/Konkurrenten, der
durch Java ersetzt werden sollte
[2] 99% aller Stellen, wo C++ unlogisch ist, folgen aus der zwingend
geforderten Rückwärtskompatibilität zu C
Axel S. schrieb:> [2] nehmen wir mal für einen Augenblick an, der Compiler befolgt deine> Interpretation "erst die rechte Seiten komplett auswerten, inklusive> aller Nebeneffekte und dann erst die Zuweisung machen" - dann steht da> am Ende das Äquivalent von>> tmp <- x (Postfix-Inkrement liefert den alten Wert, also merken)> x <- x + 1 (Inkrement-Operatur inkl. Nebeffekt)> x <- tmp (Zuweisung)>> also ein teures NOP. Soll das ernsthaft deine "Lösung" sein?
Hast du überhaupt gesehen, was da passiert ?
Erstens passiert das bei meiner "Lösung" mit Sicherheit nicht, das
ist bei Danneggers "Lösung" der Fall.
Zweitens ist das nicht meine "Lösung", sondern nur der schnellste
Weg.
Drittens, wir sind so ziemlich alle einer Meinung was das Resultat
betrifft - nur bei der Frage, ob und warum das gerade so sein muss,
gingen die Meinungen auseinander.
Auf alle Fälle gilt für mich immer noch das oben gesagte:
Marc V. schrieb:> Wenn es um Standard geht, ist es eine ganz andere Sache - da kann> auch drin stehen, dass a + 3 immer 9 ergibt, unabhängig vom Wert der> Variable a.> Wenn ich diese Sprache benutzen will, muss ich damit leben.> Genauso ist es mit a = a++;>> Ob das aber einen Sinn ergibt, ist wiederum eine ganz andere Sache.
Ich habe keinen Problem damit, aber anscheinend die anderen - wie
wagst du es überhaupt, an der Logik der C Sprache und dessen
Optimizer zu zweifeln - und ähnliches.
Marc V. schrieb:> Ich habe keinen Problem damit, aber anscheinend die anderen - wie> wagst du es überhaupt, an der Logik der C Sprache und dessen> Optimizer zu zweifeln - und ähnliches.
Es gab mal eine Diskussion darüber, warum FIAT bei einigen seinen
LKWs Lenkrad rechts eingebaut hat, obwohl die für italienischen bzw.
kontinentalen und nicht für englischen Markt vorgesehen waren.
Keiner wusste eine vernünftige Antwort darauf, aber die anfängliche
Diskussion wurde immer mehr zur Streiterei, am Ende hiess es:
- du kannst nicht fahren, du hast keine Ahnung, du hast ja nicht mal
ein Führerschein, meine Oma fährt besser als du und ähnlich.
Bis mir mal ein Nachbar, der sein Leben lang LKWs gefahren hat, die
Antwort sagte:
Weil es auf engen Gebirgsstrassen in Rechtskurven besser ist,
rechts zu sitzen, anstatt links - man kann den Abstand viel besser
einschätzen. Ob nun rechts ein Abgrund oder eine Felswand ist -
rechtssitzend sieht man halt alles besser. In den Linkskurven
dagegen ist es egal - da ist die andere Fahrbahnhälfte dazwischen.
Und genauso scheint es hier zu sein:
Keiner weiss genau warum das so ist, ob es so sein muss, ob es so
besser oder schlechter ist, aber derjenige mit einer anderen
Meinung muss ganz einfach keine Ahnung haben.
Dass sie aber selber keine vernünftige Antwort auf die Frage wissen,
tut ja nichts zur Sache - der andere ist halt dumm, stur, bockig und
ungebildet...
Marc V. schrieb:> avr schrieb:>> Wie wärs wenn du es wenigstens mal versuchst zu verstehen? Ich übersetze>> dir mal den C-Code von Peter nach Assembler falls das hilft.>> Wie wäre es wenn du dich mal ein bisschen über optimieren> informierst ?
Nirgends in C ist Optimierung gefordert. Es gibt keinen Zwang, den
schnellstmöglichen Weg umzusetzen. Man kann den Optimizer auch
ausgeschaltet lassen, und auch dann muss der Compiler korrekten Code
erzeugen.
> Das, was du so unglücklich zu übersetzen versucht hast, braucht> 2 Bytes, 2 Takte und einen Register mehr als das, was ich gepostet> habe.
Wenn dein Beispiel mit einem Compiler auf einer Architektur in einer
Situation schneller ist, läßt das nicht den Rückschluss zu, dass alle
Compiler auf allen Plattformen in allen Fällen das auch genau so
umsetzen.
Übrigens habe ich auch schon im echten Leben gesehen, das auf zwei
Systemen unterschiedliche Ergebnisse rausgekommen sind. Das ist schon
ein paar Jahre he, es waren soweit ich mich erinnern kann ein PC und
eine Sun-Workstation mit irgendeinem SPARC-Prozessor. Da ich damals auch
schon viel über das Thema undefiniertes Verhalten diskutiert habe, war
das immer das erste, was ich auf jedem System mal ausprobiert habe, um
zu sehen, ob's tatsächlich auch in der Praxis Unterschiede gibt - und es
gibt sie!