Gibt es eine feste Regel wie diese Zuweisung ausgeführt werden muss ? a=b; a=c; oder b=c a=b;
Hi Naja..ob es eine feste Regel vorhanden ist weis ich nicht. Jedoch würd ich sage: a=b; a=c; bewirkt nicht das gleiche wie: b=c; a=b; Im ersten Fall müsste c und b gleich sein, damit a=b=c ist. Wenn zb b = 3 ist und c = 4, dann steht nach abarbeitung des Codes in a=4, b hat weiters noch 3 drin stehen. Ich würd die richtige Wahl der Abfolge aufgrund von zb. dem Interrupt gewichten. Also wenn du annimmst, dass genau in der Zeile b=c der Interrupt kommt, und danach eine der Variablen verändert. Und hier halt entscheiden, welches Ergebnis du haben willst. mfg Schoasch
Ich hatte was anderes geschrieben als ich gemeint habe: Korrekt muss es natürlich so heißen: b=a; c=b; Die Reihenfolge ist mir egal, ich will nur 2 gleiche Werte in ein Register schreiben.
Der Zuweisungsoperator bindet soweit ich weiß nach rechts, a=b=c entspricht also a=(b=c). In Fällen wie diesen ist aber nicht verkehrt, zusätzliche Klammern zu setzen oder es auf zwei Anweisungen aufzuteilen. Im Assembler-Code macht das sowieso keinen Unterschied.
Christoph __ wrote:
> Im Assembler-Code macht das sowieso keinen Unterschied.
Doch ! Und dieser Unterschied hat mich ein paar Mosfets gekostet !
Es geht konkret um einen AT90PWM3 der einen Frequenzumrichter steuert.
OCR0RB = PWM0A;
OCR1RA = PWM0A;
wird zu:
171 0100 9093 D900 sts (216)+1,r25
172 0104 8093 D800 sts 216,r24
173 .LM16:
174 0108 9093 E500 sts (228)+1,r25
175 010c 8093 E400 sts 228,r24
OCR1RA = OCR0RB = PWM0A;
wird zu:
163 00ee 9093 D500 sts (216)+1,r25
164 00f2 8093 D400 sts 216,r24
165 00f6 8091 D400 lds r24,216
166 00fa 9091 D500 lds r25,(216)+1
167 00fe 9093 E900 sts (228)+1,r25
168 0102 8093 E800 sts 228,r24
Das Problem ist nur: Die Register sind Write only !!!
Seltsamerweise funktioniert das ganze in 99% der Zeit trotzdem, aber ab
und zu gibt es ein paar Aussetzer bei der PWM und dann knallte es mal
kurz und die Mosfets waren im Raum verteilt...
Und jetzt interessiert mich, ob das ein Compilerbug ist, oder ob das nur
ein dummer Zufall war, da es vermutlich in >99% aller Fälle egal, ist
wierum der Compiler es macht (außer in diesem und in dem
Interruptbeispiel von Schoasch.)
es wird folglich a=(b=c); Der Assembler-Code ist dann auch logisch, weil b in deinem falls volatile ist.
Zuweisungsausdrücke sind rechtsassoziativ. Wenn a, b, c Variable sind, ist a = b = c <=> a = (b = c)
Grundsätzliche Regel: Kurzschreibweise wenn möglich vermeiden! Ich den meißten Fällen nutzen Programmierer diese Kurzschreibweise eigentlich nur dazu, um sich als Programmiergott zu profilieren. Dies ist jetzt nicht auf dich bezogen.
Ich nutze die Kurzschreibweisen häufig, um Zeit zu sparen. Gegen so Sachen wie x+=2 usw. ist ja normalerweise nichts einzuwenden. Vor allem bei langen Namen spart das einiges an Zeit. Ebenso (!x) für (x==0). Das Problem ist meistens nur, dass es eben ein paar Sonderfälle gibt (wie hier) wo man schnell drauf rein fällt. Die Ursache liegt meistens beim fehlenden Wissen. Ich werde x=y=z ab jetzt definitv vermeiden, da ich bis heute dachte x und y hätten danach den Wert von z und nichts anderes. Gibt es eigentlich irgendwo die offizielle Beschreibung von ANSI C ? Also nicht nur die Sprache, sondern auch wie der Compiler das umzusetzen hat ? Im Kernighan & Ritchie steht einiges drin, aber eben leider doch nicht alles. Vor allem bei einigen Details ist dieses ansonsten sehr gute Buch schnell an der Grenze.
a = b = c; bedeutet a = (b = c); bzw. ausgeschrieben: b = c; a = b; Und wenn b volatile ist, muß es eben zurückgelesen werden für die Zuweisung c = b; Wenn nun b falsche Werte liefert, kann der Compiler nichts dafür. Ein anderer beliebter Fehler ist, wenn a und c 16 bit sind, b aber nur 8 Bit. Dann kriegt a natürlich nicht das Highbyte von c, sondern b vorzeichenrichtig erweitert. Peter
Peter Dannegger wrote: > a = b = c; bedeutet a = (b = c); bzw. ausgeschrieben: > > b = c; > a = b; Außer dass a = b = c eben nur einen "sequence point" (nach der kompletten Anweisung) besitzt, während die zweite Variante zwei davon hat. Bei der zweiten Variante ist sichergestellt, dass falls b volatile ist, dessen Wert vor der Zuweisung von a den Wert von c hat, und b wird in diesem Falle vor dem Zuweisen nach a auch nochmal zurück gelesen. Im ersten Falle ist es selbst bei volatile qualifizierten Objekten a und/oder b nicht sicher, in welche Reihenfolge die Zuweisung an a und b erfolgt. Die Rechtsassoziativität besagt nicht, in welcher Reihenfolge der Compiler die Aktionen ausführen muss, sondern nur, in welcher Reihenfolge er den Ausdruck parsen muss (d. h. welche Klammer implizit gesetzt wird). Die volatile-Bestimmung besagt weiterhin lediglich, dass die Werte von volatile-Objekten an einem sequence point zurückgeschrieben sein müssen, d.h. sie bestimmen nicht etwa die Reihenfolge des Schreibens von a und b innerhalb der Zuweisungsanweisung. > Und wenn b volatile ist, muß es eben zurückgelesen werden für die > Zuweisung c = b; > Wenn nun b falsche Werte liefert, kann der Compiler nichts dafür. Das bleibt natürlich trotzdem, auch und gerade für den zweiten Fall.
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.