Forum: Compiler & IDEs Problem bei If Bedingung


von joe (Gast)


Lesenswert?

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?

von Juhu (Gast)


Lesenswert?

Nix.

vol_1 muss halt nur aus was anderes als 0xFF gesetzt werden dass der 
Ausdruck wahr wird...

von Frank B. (frank_b) Benutzerseite


Lesenswert?

Versuchs mal mit

"unsigned char vol_l=0xFF;"

von Michael G. (glunzl)


Lesenswert?

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

von joe (Gast)


Lesenswert?

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.

von Michael G. (glunzl)


Lesenswert?

Das ist dann unsigned char, oder uint8_t, siehe Link!

Michael

von joe (Gast)


Lesenswert?

Ja stimmt es muss Unsigned sein.

Aber schon Komisch auch beim memory Windows im AVR studio
hat er die speicherzellen als FF angezeigt.

von Rolf Magnus (Gast)


Lesenswert?

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

von Andreas K. (a-k)


Lesenswert?

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.

von Werner B. (Gast)


Lesenswert?

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.

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


Lesenswert?

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.

von Michael Wilhelm (Gast)


Lesenswert?

>...macht daraus (gedanklich) eine ...

Nette Formulierung

MW

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


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Frank B. (frank_b) Benutzerseite


Lesenswert?

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