Forum: Compiler & IDEs a=b=c


von Benedikt K. (benedikt)


Lesenswert?

Gibt es eine feste Regel wie diese Zuweisung ausgeführt werden muss ?

a=b;
a=c;

oder

b=c
a=b;

von Schoasch (Gast)


Lesenswert?

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

von Benedikt K. (benedikt)


Lesenswert?

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.

von Christoph _. (chris)


Lesenswert?

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.

von Benedikt K. (benedikt)


Lesenswert?

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

von Henning (Gast)


Lesenswert?

es wird folglich
a=(b=c);

Der Assembler-Code ist dann auch logisch, weil b in deinem falls 
volatile ist.

von Henning (Gast)


Lesenswert?

ich meine
b=c;
a=b; //!!!!

von C-Guru (Gast)


Lesenswert?

Zuweisungsausdrücke sind rechtsassoziativ.
Wenn a, b, c Variable sind, ist
   a = b = c  <=> a = (b = c)

von Benedikt K. (benedikt)


Lesenswert?

OK, danke.
So schnell kann eine "Kurzschreibweise" nach hinten los gehen...

von katzeklo (Gast)


Lesenswert?

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.

von Benedikt K. (benedikt)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

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


Lesenswert?

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