www.mikrocontroller.net

Forum: Compiler & IDEs Problem bei If Bedingung


Autor: joe (Gast)
Datum:

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

Autor: Juhu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nix.

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

Autor: Frank B_. (frank_b) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal mit

"unsigned char vol_l=0xFF;"

Autor: Michael Glunz (glunzl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Char ist signed geht von -128 bis +127. Siehe 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
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

Autor: joe (Gast)
Datum:

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

Autor: Michael Glunz (glunzl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist dann unsigned char, oder uint8_t, siehe Link!

Michael

Autor: joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja stimmt es muss Unsigned sein.

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

Autor: Rolf Magnus (Gast)
Datum:

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

Autor: Andreas K. (a-k)
Datum:

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

Autor: Werner B. (Gast)
Datum:

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

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

Bewertung
0 lesenswert
nicht lesenswert
Werner B. wrote:

> Was funktionieren muss ist z.B.
>
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:
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.

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>...macht daraus (gedanklich) eine ...

Nette Formulierung

MW

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

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: Frank B_. (frank_b) Benutzerseite
Datum:

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

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.