Problem bei If Bedingung

Gast #731434
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.
#731478
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.
Gast #731489
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.
Moderator Persönliche Seite #731524
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.
Moderator Persönliche Seite #731605
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.
#731621
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren