Werner B. schrieb:
> Etwas Offtopic:
>
> Bei AVRGCC/WinAVR wird kürzerer Coder erzeugt wenn man bei
> Optimierungsstufe -Os statt
>
>
>
1 | > inta=(int16 & 0xFF00) >> 8;
|
2 | >
|
> verwendet. Das Erste wird in in acht Schieboperationen übersetzt und
> dann der Wert nach inta kopiert, beim Zweiten wird direkt das High-Byte
> nach inta kopiert.
Das stimmt so nicht. Jedoch hast Du teilweise recht: Das Rechts-Schieben
von vorzeichenbehafteten ints bringt öfters andere Ergebnisse, als man
erwartet. Hier ein Auszug aus dem lss-File des WinAVR-Compilers:
-------------------------------------------------------------
A:
int8_t
xyz (int16_t i16)
{
int8_t i8;
i8 = i16 >> 8;
return (i8);
}
Ergebnis:
70: 89 2f mov r24, r25
72: 99 0f add r25, r25
74: 99 0b sbc r25, r25
76: 08 95 ret
-------------------------------------------------------------
B:
int8_t
xyz (int16_t i16)
{
int8_t i8;
i8 = (i16 & 0xFF00) >> 8;
return (i8);
}
70: 89 2f mov r24, r25
72: 08 95 ret
-------------------------------------------------------------
C:
uint8_t
xyz (uint16_t i16)
{
uint8_t i8;
i8 = i16 >> 8;
return (i8);
}
70: 89 2f mov r24, r25
72: 08 95 ret
-------------------------------------------------------------
Deswegen schrieb ich ja: Beim Schieben von Ganzzahlen ist es meist
sinnvoll, unsigned-Typen zu verwenden.
Woran liegt das? Wenn man negative Werte nach rechts schiebt, muss das
Vorzeichen erhalten bleiben.
Beispiel (unter Linux übersetzt):
#include <stdio.h>
#include <inttypes.h>
main ()
{
char i = 0x80;
i >>= 1;
printf ("%d\n", i);
}
Das Ergebnis ist -64, also binär 11000000. Aus 1 Vorzeichen-Bit werden
plötzlich 2 Einsen, siehe Zweierkomplement.
Gruß,
Frank