www.mikrocontroller.net

Forum: Compiler & IDEs a=b=c


Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es eine feste Regel wie diese Zuweisung ausgeführt werden muss ?

a=b;
a=c;

oder

b=c
a=b;

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christoph __ (chris)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
es wird folglich
a=(b=c);

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

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich meine
b=c;
a=b; //!!!!

Autor: C-Guru (Gast)
Datum:

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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, danke.
So schnell kann eine "Kurzschreibweise" nach hinten los gehen...

Autor: katzeklo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.