Ich möchte gerne die Feldinhalte eines u08 Feldes (erg8) in das nieder- und höherwertige Byte einer u16 Variablen (abc) bringen und das Ganze möglichst ohne zeitaufwendige Bitschiebereien. Dabei habe ich mir folgende Lösung ausgetüftelt (Beispiel): typedef unsigned char u08; typedef unsigned short u16; int main(void) { u16 *ptr16,abc; u08 erg8[1]; ptr16 = &abc; erg8[0] = 0x55; erg8[1] = 0xaa; *((u08 *)ptr16+1) = erg8[1]; *(u08 *)ptr16 = erg8[0]; } Jedenfalls meckert mein Compiler dabei nichts an und auch ein Test mit einem Debugger unter Linux (gcc) zeigt keine "Unsauberkeiten" und, last but not least, es läuft und bringt das erwartete Ergebnis. Trotzdem habe ich bei diesem Code irgendwie ein ungutes Gefühl. Kennt jemand für diese Problematik eine bessere oder schönere Lösung? Ist der Code oben korrekt oder fällt das schon unter die Rubrik "unsaubere Tricks"? Vielen Dank! Gruss, Peter
Die Bitschiebereien bei z.B. a=0xFF&(b>>8) werden von avr-gcc vollständig wegoptimiert. Gruß Andreas
Danke für die Auskunft, aber irgenwie bleiben doch noch Fragen offen.
> Die Bitschiebereien bei z.B. a=0xFF&(b>>8) werden von avr-gcc vollständig
wegoptimiert.
Naja, so vollständig wird er sie ja nicht wegoptimieren ;-)
Schliesslich soll er hier ja noch etwas tun.
Ist mein Code denn wenigstens ok und gibt es vielleicht noch andere
Ideen?
Gruss,
Peter
Vorschlag: #include <io.h> #include <progmem.h> #include <stdlib.h> typedef union conv CONV; union conv{ struct{ unsigned char s_[2]; }s; unsigned short d; }; static CONV conv_local; static unsigned short ergebnis; int main(void) { conv_local.s.s_[0] = 0x55; conv_local.s.s_[1] = 0xaa; ergebnis = conv_local.d; }
Du suchst eine Lösung für ein Problem das nicht existiert. AVR-GCC optimiert die Bitschiebereien NATÜRLICH vollständig weg, er liest im oben genannten Beispiel einfach den Inhalt der passenden Stelle im Speicher. Schau dir halt mal den erzeugten Assemblercode an.
Warum machst Du es nicht mit UNION ? union xyz { unsigned char Bytefeld[2]; unsigned int Integer; }
Hallo Matthias & Sebastian, danke für den Tip mit dem union! Manchmal sieht man den Wald vor Bäumen nicht ;-) Das ist die elegante Lösung, nach der ich gesucht habe! Man könnte sogar noch auf dem selben Speicherplatz ein Bitfeld anlegen und so elegant auf die einzelnen Bits (bitte ein Bit!) zugreifen. C ist ja doch eine tolle Programmiersprache, sofern man sie beherrscht. Aber das schaffe ich eines Tages auch noch. Gruss, Peter
was ist denn mit dieser variante: int main(void) { u16 abc; u08 erg8[1]; erg8[0] = 0x55; erg8[1] = 0xaa; abc = erg8[0] + (erg[1]<<8); } sollte doch zum selben ergebnis führen, oder?
Wie sieht das eigentlich mit Felddeklarationen bei gcc aus? Im Ansi-C würde "u08 erg8[1];" nur ein Feld mit EINEM Eintrag (Index = 0) erzeugen. Das ist doch mit gcc bestimmt nicht anders, oder? Daraus würde dann folgen: u08 erg8[2]; //mit Indizes 0 und 1 Falls einer eine gegesätzliche Auffassung hat, kann er das ja mal posten. ;-)
@Dirk Ich habe mich in meinem Code oben vertan. Es muss natürlich ein Feld mit 2 Elementen deklariert werden, also u08 erg8[2]; Somit kann man auf erg8[0] und erg8[1] zugreifen. Übrigens ein Fehler, der in C gerne von Anfängern gemacht wird, womit ich mich hier mal wieder verraten habe ;-) @Jonas natürlich kann man das so auch schreiben. Ich fand es nur etwas unelegant, das ist alles. Gruss, Peter
hmm, find ich persönlich eleganter, weil nur 1 zeile... aber is wohl geschmackssache. :-)
Wieso nur eine Zeile? Wenn ich z.B. ein union definiere, brauche ich überhaupt nichts mehr zu transferieren, also nach Deiner Rechnung wären das dann null Zeilen, sowas finde ich z.B. eleganter! mit :-) Gruss Peter
hmm, da haste recht, das mit der union ist eleganter. ich hatte meins nur mit deinem ursprünglichen verglichen...
Ich finde es übertrieben, für sowas extra eine union zu nehmen. Definier dir doch einfach ein Makro, z.B. #define HIGH_BYTE(x) (0xFF&(x>>8)) Das macht den Code auch übersichtlicher.
@Andreas Du lässt einfach nicht locker ;-) Dabei muss es, wenn schon mit Bitschieberei und Makro so heissen: #define HIGH_BYTE(x) (0xFF&(x<<8)) Ok, ich frage ganz einfach meine Lebensgefährtin was ihr besser gefällt. Die hat zwar keine Ahnung von C, dafür weiss sie jedoch immer alles besser und hat letztendlich doch immer Recht ;-) Gruss, Peter
> Lebensgefährtin [...] hat letztendlich doch immer Recht ;-) Na dann bist du wohl auch nicht erstaunt, daß sie Andreas' Lösung favorisiert, oder?! (Es soll ja das Highbyte zurückgeliefert, und nicht eines generiert werden, oder?) Ansonsten: > #define HIGH_BYTE(x) (0xFF&(x<<8)) Bei deinem Ansatz wäre das Ergebnis immer 0. Besser: #define HIGH_BYTE(x) (x<<8) Schmittchen.
? Das funktioniert doch beides nicht. (0xFF&(x>>8)) war schon richtig (wobei man sich das 0xFF& eigentlich sparen kann da bei >> Nuller nachgeschoben werden). Gruß Andreas
@Andreas: Auf was bezieht sich: > Das funktioniert doch beides nicht. ? Ich war mir nicht sicher, was die Ursprungsfrage eigentlich war: a.) Es soll das Highbyte zurückgegeben werden, dann gilt: > Andreas' Lösung favorisiert (also deine Lösung (Andreas) sollte stimmen) oder b.) Es soll ein Highbyte generiert werden - um am Ende dann zusammen mit einem (Low)Byte ein 16Bit-Wert zu repräsentieren: > #define HIGH_BYTE(x) (x<<8) (setzt natürlich voraus, daß x als 16Bit-Variable deklariert ist... achso, eben hab ich dich verstanden: Wenn er es schon als 16Bit-Variable deklarieren muß, dann braucht die 2 8Bit-Variablen im Nachhinein nicht mehr zusammen zu tricksen.) Aus Peters letzter Antwort war nicht eindeutig erkennbar, was er eigentlich will. In seinem ersten Posting klang das alles mehr nach generieren eines 16Bit-Wertes aus 2 8Bit-Werten. Schmittchen, leicht verwirrt.
Stimmt, du hast recht, ich hatte gedacht er wollte es umgekehrt haben. Mein Fehler.
@Andreas Du hast Recht, die Bits müssen natürlich nach rechts geschoben werden. Und das Ausmaskieren kann man sich natürlich auch sparen. Also so sollte es dann richtig heissen: #define HIGH_BYTE(x) (x>>8) ok? Sehrwahrscheinlich sind das noch so Erinnerungsfragmente, wo ich mal an little-Endian Systemen programmiert hatte. Ich glaube, da war das alles irgendwie anders herum. Gruss, Peter
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.