Hallo, Ich möchte gern folgende If Abfrage realisieren: char vol_l=0xFF; if (vol_l != 0xFF) { } leider ist die if Abfrage nie wahr. Was ist denn an der Syntax falsch?
Nix. vol_1 muss halt nur aus was anderes als 0xFF gesetzt werden dass der Ausdruck wahr wird...
Char ist signed geht von -128 bis +127. Siehe http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ganzzahlige_.28Integer.29_Datentypen Ich weiss nicht wie "char vol_l=0xFF" umesetzt wird, allerdings kann 0xFF = 255dez nicht in sinvoll in char abgebildet werden. Oder man korrigiert mich gleich :-) Gruß Michael
Hallo, also ich hab es jetzt mal mit int8_t probiert. Ich möchte eigentlich nur einen Datentyp haben, der 8 Bit groß ist im maximal Hex FF abzubilden.
Ja stimmt es muss Unsigned sein. Aber schon Komisch auch beim memory Windows im AVR studio hat er die speicherzellen als FF angezeigt.
> Ich weiss nicht wie "char vol_l=0xFF" umesetzt wird,
Hängt davon ab, ob char auf der gewünschten Zielplattform signed oder
unsigned ist. Wenn es signed ist, wird 0xFF konvertiert zu -1. Das
sollte aber auch beim Vergleich im if passieren.
joe wrote: > Aber schon Komisch auch beim memory Windows im AVR studio > hat er die speicherzellen als FF angezeigt. Memory-Dumps sind immer typ- und vorzeichenlos. Oder willst du da 55 60 41 -16 00 -1 20 lesen müssen? Im Handbuch des Compilers findet sich gewöhnlich ein Abschnitt, der den Wertebereich jedes Datentyps angibt. Nützlich: Alle Warnungen des Compilers einschalten. Bei GCC wäre das -Wall.
Da sich der AVR-GCC an den ISO C Standard hält wird die Konstante 0xFF als int Wert behandelt (16-Bit 0x00FF). Um einen 16-Bit Wert mit einem 8-Bit Wert vergleichen zu können müssen zuerst die 8 Bit auf 16 erweitert werden. Da die 8 Bit aber vorzeichenbehaftet sind, wird das mit Vorzeichen gemacht. Somit wird aus 0xFF -> 0xFFFF und dein Vergleich misslingt. Was funktionieren muss ist z.B.
1 | if(vol_l != (uint8_t)0xFF) |
Hier wird auch die Erweiterung auf 16 Bit verhindert was auch zu kürzerem und schnellerem Code führt.
Werner B. wrote: > Was funktionieren muss ist z.B. >
1 | if(vol_l != (uint8_t)0xFF) |
> > Hier wird auch die Erweiterung auf 16 Bit verhindert Nein, wird sie nicht. ;-) Das Ganze nennt sich integer promotion und führt dazu, dass implizit beide Seiten des Vergleichs auf mindestens den Typ `int' erweitert werden (auf `unsigned int' oder mehr, falls die Daten nicht anders abbildbar sind, aber das ist nicht der Fall). Dabei passiert der 0xFF nichts, die bleibt die 0x00FF, die sie implizit schon war. Da aber vol_l einen vorzeichenbehafteten Typ hatte, wird deren Inhalt durch die integer promotion nach wie vor auf 16 bits erweitert, und zwar zuerst einmal vorzeichenbehaftet. Damit wird aus dem Bitmuster 0xFF (das bei signed char ja eine -1 darstellt) das Bitmuster 0xFFFF (das bei signed int eine -1 darstellt), erst danach kommt logisch gesehen der Vergleich. Dieser wiederum hat auf der rechten Seite ein unsigned int stehen und wird damit unsigned durchgeführt, d. h. es wird 0xFFFF gegen 0x00FF verglichen. Das hätte besonders nette Resultate, wenn man auf > vergleichen würde... dann wären nämlich alle Werte ab 0x80 in vol_l plötzlich sogar größer als die 0xFF auf der rechten Seite. Was (außer der richtigen Lösung, alles als uint8_t zu deklarieren) noch helfen würde ist:
1 | if((uint8_t)vol_l != 0xFF) |
In diesem Fall wird die -1 aus vol_l zuerst in ein 0xFF umgewandelt, und die integer promotion macht daraus (gedanklich) eine 0x00FF. Das passiert auf der rechten Seite auch, und schon passt es. Die Optimierung kann natürlich hinterher die Behandlung des high bytes wieder rauskicken.
Michael Wilhelm wrote: >>...macht daraus (gedanklich) eine ... > > Nette Formulierung Soll halt nur heißen, dass die integer promotion es nicht zwingend erfordert, dass der Compiler in der Tat mit 16-bit-Werten rechnet. Es greift hier die sogenannte “as if rule”: das Ergebnis muss sich so verhalten, als wäre sie erfolgt.
Jörg Wunsch wrote: > Die Optimierung kann natürlich hinterher die Behandlung des high > bytes wieder rauskicken. Ja schön wärs, wenn er mal die tonnenweisen "eor r25,r25" ohne nachfolgende r25-Benutzung rauskicken würde. 1% Codeeinsparung wären da bestimmt drin. Peter
...man könnte ja mal einen "externen" optimizer programmieren, der sich den erzeugten Maschinencode vornimmt und solche Sachen herauswirft. Wär doch was. Im Falle des eor r25,r25 stelle ich mir das nicht allzu schwierig vor. Frank p.s. kann man die *.lss - Datei eigentlich erfolgreich durch den Assembler schicken ?
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.