Unsigned Char vergleich beim AVR GCC

OP #284350
Lesenswert?
• ▲
▼
Hallo Leute,

ich habe jetzt schon diverse stellen gefunden, die der GCC einfach mal
miserabel löst. Hier die für mich bedeutenste:
1
  44:dcf77.c       ****     if ((unsigned char)((unsigned
2
char)dcf77_State & (unsigned char)DCF77_StateMask) != (unsigned
3
char)DCF77_StateSense) return;
4
 147                 .LM5:
5
 148 0016 8091 0000     lds r24,dcf77_State
6
 149 001a 9927          clr r25
7
 150 001c 8C70          andi r24,lo8(12)
8
 151 001e 9070          andi r25,hi8(12)
9
 152 0020 0C97          sbiw r24,12
10
 153 0022 41F4          brne .L2

Es ist alles nach (unsigned char) gecastet und dennoch macht der gcc
daraus eine Integer operation (16 Bit). Erst wenn ich eine Register
variable definiere, die den berechneten Wert erhält, wird der Vergleich
ein simpler 8-Bit-Vergleich:
1
  43:dcf77.c       ****   register unsigned char temp = (dcf77_State &
2
DCF77_StateMask);
3
 146                 .LM5:
4
 147 0014 8091 0000     lds r24,dcf77_State
5
 148 0018 8C70          andi r24,lo8(12)
6
  45:dcf77.c       ****   if (temp != DCF77_StateSense) return;
7
 150                 .LM6:
8
 151 001a 8C30          cpi r24,lo8(12)
9
 152 001c 41F4          brne .L2

Wieso bekommt er das nicht auch schon beim casten hin oder merkt es gar
selber, dass nur 8-bit-Werte beteiligt sind?

Irgendwie hat Assembler schon so seine Vorteile.

Schöne Grüße, Clemens
Gast #284354
Lesenswert?
• ▲
▼
Wenn man im eigenen Programm konsequent die Typen aus stdint.h
verwendet, ist -mint8 nur dann Problem, wenn man 32bit braucht und
nicht ersatzweise mit 64bit leben kann. Oder wenn man printf() und
ähnliche aus der libc benötigt.

Der C Standard verlangt zwar, dass int >= 16bit und dass alle Rechnung
so ausgeführt wird, als ob alles kleinere zu 16bit konvertiert wird.
Aber er verlangt natürlich nur, dass das Ergebnis diesem Verfahren
entspricht. Wenn sich das exakt gleiche Ergebnis wie hier mit reiner
8bit-Rechnung ermitteln lässt - warum nicht?

Es gibt schon so ein paar Ecken im Compiler, die einen erstaunen
können. So neigt er bei manchen 2-er-Potenz Bitmasken dazu, den
Operanden erst umständlichst nach rechts zu schieben um dann Bit 0
testen zu können, statt gleich auf's gewünschte Bit loszugehen. Nobody
is perfect, auch gcc/avr nicht.
Moderator Persönliche Seite #284355
Lesenswert?
• ▲
▼
> Wenn sich das exakt gleiche Ergebnis wie hier mit reiner
> 8bit-Rechnung ermitteln lässt - warum nicht?

Klar, es müsste ihm ,,nur'' jemand beibiegen.  Da alle
Architekturen,
für die am GCC ,hauptberuflich' gebaut wird, dieses Problem aber
nicht
haben (deren Register sind eh' alle 32 bits breit), muss sich da wohl
jemand aus der Microcontroller-Ecke drum kümmern, dass derartige
Optimierungen eingebaut werden.
Gast #284356
Lesenswert?
• ▲
▼
Das ist ja das ulkige daran, die Optimierungen sind schon drin. Meist
macht er es auch richtig, nur manchmal nicht, dann aber ist jeder Cast
wirkungslos. Eine Logik dahinter konnte ich noch nicht erkennen.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.