timeout wird in einem Interrupt erhöht.
Mit keiner Optimierung läuft der Code.
Mit Optimierung -Os (Standard in AVR Studio),
läuft der Code nicht, er bleibt irgendwie/wo
an
1
while((!(UCSR1A&(1<<RXC1)))&&(timeout<50))
2
;
hängen.
Könntet ihr mir helfen? Irgendwo muss ich Mist gebaut haben - aber ich
steh auf dem Schlauch :(
Viele Grüße
Daniel
Hi
Meiner Meinung nach ist das
while ( (!(UCSR1A & (1<<RXC1))) && (timeout<50) );
so nicht richtig.
In C/C++ ist && ein lazy and, das bedeuted, dass die zweite Bedingung
nur geprüft wird wenn die erste true ist.
Falls du kein Zeichen empfängst ist die erste Bedingung immer false,
daher wird nie auf den Timeout geprüft.
Richtig sollte es heißen:
while ((timeout<50) && (!(UCSR1A & (1<<RXC1))));
Das ganze passiert nur bei aktivierter Optimierung, da der Compiler erst
dann das lazy and nutzt.
mfg Manuel
Der ganze Code ist etwas lang, aber deine Glaskugel hat vollkommen
recht und klingt auch sehr plausibel. Werde ich gleich mal testen :)
Vielen, vielen Dank
Manuel Andreu schrieb:
> Meiner Meinung nach ist das>> while ( (!(UCSR1A & (1<<RXC1))) && (timeout<50) );>> so nicht richtig.>> In C/C++ ist && ein lazy and, das bedeuted, dass die zweite Bedingung> nur geprüft wird wenn die erste true ist.>> Falls du kein Zeichen empfängst ist die erste Bedingung immer false,> daher wird nie auf den Timeout geprüft.
Nein, sie ist dann immer true, und timeout wird zum entscheidenden
Faktor, so wie es auch gedacht ist.
> Richtig sollte es heißen:>> while ((timeout<50) && (!(UCSR1A & (1<<RXC1))));
Das Tauschen der beiden &&-Operanten hat hier keinerlei Auswirkungen.
Beide Varianten sind richtig. Das Problem wird ein fehlendes volatile
sein.
Manuel Andreu:
> In C/C++ ist && ein lazy and, das bedeuted,> dass die zweite Bedingung nur geprüft wird> wenn die erste true ist.
So weit stimmts.
> Das ganze passiert nur bei aktivierter Optimierung,> da der Compiler erst dann das lazy and nutzt.
Das stimmt nicht. && ist immer lazy, auch ohne Optimierung.
tuppes schrieb:
> Manuel Andreu:>> In C/C++ ist && ein lazy and, das bedeuted,>> dass die zweite Bedingung nur geprüft wird>> wenn die erste true ist.>> So weit stimmts.>>> Das ganze passiert nur bei aktivierter Optimierung,>> da der Compiler erst dann das lazy and nutzt.>> Das stimmt nicht. && ist immer lazy, auch ohne Optimierung.
Noch ein kleiner Nachtrag:
... und das ist auch wichtig, dass das so ist. Letztendlich garantiert
mir dieses geforderte Verhalten, dass eine Abfrage
1
if(Pointer&&Pointer->Member)
die NULL-Pointer Behandlung korrekt ausführt und keinen ungültigen
Member-Zugriff nach sich zieht. In anderen Sprachen, zb Ur-Pascal, war
das nicht so und hat unnötig tief verschachtelten Code nach sich
gezogen.
PS2: Der Ausdruck 'lazy' ist dafür in C/C++ unüblich. Man spricht hier
meist von 'shortcut evaluation'
tuppes schrieb:
>> Das ganze passiert nur bei aktivierter Optimierung,>> da der Compiler erst dann das lazy and nutzt.>> Das stimmt nicht. && ist immer lazy, auch ohne Optimierung.
Ich hab gcc schon Code erzeugen gesehen, wo er die zweite Bedinung
auswertete, obwohl die erste falsch war. Erst dachte ich an nen Bug,
aber es war nur in Fällen, wo kein Speicherzugriff erfolgte; es ging um
reine Arithmetik und die Maschine verfügte über Befehle, die (A' & B')
für bestimmt Ausdrücke A' und B' effizient auswerten konnte, und die die
gleichen Effekte auf die Maschine hatten, als (A && B), wobei A und A'
bzw. B und B' in bestimmten Zusammenhang standen.
Womöglich erkennte die Analyse, daß B unabhängig von A war.
Es war aber in allen Fällen so, daß der Code korrekt war und was auf der
Maschine abging nicht der C-Semantik widersprach.
Johann
Johann L. schrieb:
> Es war aber in allen Fällen so, daß der Code korrekt war und was auf der> Maschine abging nicht der C-Semantik widersprach.
Tja. Das ist schwer zu beurteilen ohne den konkreten Code und die
konkrete Maschine. Mgwl. hat der Optimizer rausgefunden, dass die
Evaluierung billiger ist, als eine Abfrage samt conditional Branch samt
eventuellem Pipeline Reloading.
Rein formal muss der Compiler aber bei einem && den 2-ten Ausdruck
unausgewertet lassen, wenn der erste bereits falsch ist.
Und dann gibts natürlich noch die 'As-if' Regel. Der Optimizer darf den
Code umstricken wie er lustig ist, solange sich das Ergebnis so verhält,
'as-if' der Optimizer nie am Werke war. Dass der gcc bei dem von dir
beobachteten Fällen einen Fehler gemacht hat, glaub ich nicht wirklich.
Solche Shortcuts werden oft ausgenutzt, sodass man auf fehlerhaftes
Verhalten schnell aufmerksam werden würde. Auf der anderen Seite machen
Optimizer heutzutage Analysen, die sollte man nicht für möglich halten.
Ich mag da nicht mehr up to date sein, aber früher hat der Standard dem
Compiler die Entscheidung überlassen, in welcher Reihenfolge die Zweige
von logischen Verknüpfungen überprüft werden und ob alle Zweige
überprüft werden oder nur die nötigen. Da war das geschilderte Verhalten
lediglich das spezifische Verhalten von gcc, nicht unbedingt von allen
Compilern.
ein schrieb:
> Ich mag da nicht mehr up to date sein, aber früher hat der Standard dem> Compiler die Entscheidung überlassen, in welcher Reihenfolge die Zweige> von logischen Verknüpfungen überprüft werden und ob alle Zweige> überprüft werden oder nur die nötigen.
Nein, in C war das schon immer definiert.
Wie's aussieht, hab ich das in der Erinnerung wohl mit den
Funktionsparametern verwechselt. Operatoren haben in der Tat eine
definierte Assoziativität.
ein schrieb:
> Operatoren haben in der Tat eine> definierte Assoziativität.
Es geht hier nicht um die Assoziativität, sondern ausdrücklich
darum, dass die Argumente von && und || von links nach rechts
dergestalt bewertet werden müssen, dass die Evaluierung des
Ausdrucks abgebrochen wird, sowie sein logisches Ergebnis
eindeutig feststeht.
Karl heinz Buchegger schrieb:
> Und dann gibts natürlich noch die 'As-if' Regel. Der Optimizer darf den> Code umstricken wie er lustig ist, solange sich das Ergebnis so verhält,> 'as-if' der Optimizer nie am Werke war.
Jo, der berühmte Unterschied zwischen der abstrakten Maschine und der
realen Maschine ;-)
Johann