Hallo, ich würde gerne möglichst effizient CAN Nachrichten auswerten. Diese bestehen immer aus 1..8 zusammenhängenden Bytes. Beispielsweise kann ein Signal bei bit 2 starten und 10bit lang sein. Ich wollte nun schrittweise immer zwei Byte (damit maximal 16Bit breite Worte) mit einem Short-Zeiger auswählen und dann mit entsprechender Maskierung verUNDen. Leider lässte der kompiler die conversion von char* zu short int* nicht zu. Folgendes wollte ich also tun: short * block; char msg[]="ABCDEFG"; /*lenght soll die länge meine wortes in bit angeben, starbit ist selbsterklärend*/ block = &msg; // also damit sollte der short auf das untere Byte zeigen block = block & ((short)(pow(2,length) << startbit)); nun sollte eigentlich meine nachrichtig fertig maskiert in block stehen, sodass ich diese nur wieder um startbit in die gegenrichtung shiften müsste. gibt es vielleicht eine elegantere lösung, um aus einem 2er Byteblock einen beliebig langen (max16) bitblock zu lesen? grüße und danke für ideen, toby
Hi! Deklariere doch einfach ein bitfield Typen. Das ist imho die Art, sowas zu tun.
Danke, aber das hilft mir nicht viel weiter. Ich kann doch bits aus bitfelder nicht mit einem befehl beschreiben, jedenfalls steht das nirgends in den definitionen... für den fall ich hätte ein bitfeld mit b0 bis b7 wäre ein befehl: bitfeld.b0 = 0x41; recht brauchbar, wenn er die anderen bits nach b0 überschreiben würde. funktioniert aber nicht. Weitere tips? gruß, toby
2 Sachen: 1. pow() ist eine float-Funktion, d.h. es dauert ewig lange und kostet zich kB Code. Beschäftige dich besser mal mit Schiebeoperatoren. 2. Die Byteorder in mehrbytigen Variablen ist nicht definiert. Was auf der einen CPU mit dem einen Compiler funktioniert, kann Dir mit ner anderen großen Mist produzieren. Daher macht man es üblicher Weise kompatibel:
1 | short val = byte_low | (byte_high << 8); |
Um nun z.B. die Bits 2..9 zu extraieren, maskiert man oben und schiebt nach unten:
1 | val9_2 = (val & (1 << 9 + 1) - 1) >> 2; |
Peter
Hallo Peter! Vielen Dank für die Hilfe, die Möglichkeiten der Bitoperationen habe ich, wie es scheint, nicht ausgenutzt. Ich versuche gerade die Bitextraktion zu verstehen. Irgendwie steh ich auf dem Schlauch. val9_2 = (val & (1 << 9 + 1) - 1) >> 2; Wie läuft dieser Vergleich ab? wozu die -1? Welche Operation hat vorrang in der klammer? vielleicht ist es einfach schon ein bisschen spät! Auf jeden Fall funktioniert es schon mal! Gruß, Toby
> Wie läuft dieser Vergleich ab In diesem Ausdruck ist kein einziger Vergleich! >> bedeutet 'bitweise nach rechts schieben' << 'bitweise nach links schieben' i = k << 2; der Inhalt wird also um 2 Bits nach links verschoben und das Ergebnis wird i zugewiesen. Zu deinem ursprünglichen Ansatz: > leider .. char* zu short int* nicht zu. Ja, klar. Ein Pointer auf int ist nunmal kein Pointer auf char. Wenn du allerdings sicher bist, dass du genau das willst, dass der Compiler so tut, als ob der Pointer auf char einer auf int wäre, kannst du ihn immer überstimmen: mit einem Cast block = (short*) &msg; Aber Vorsicht: Ein Cast ist eine Waffe. Effektiv schaltest du damit das Typ-Prüfsystem des Compilers ab und zwingst ihn die Zuweisung wider besseren Wissens zu akzeptieren. Der Programmierer sollte also besser wissen was er hier tut. Die Anmerkungen bezüglich Nicht-Portabilität gelten natürlich weiterhin.
> aber was macht die -1?
Probiers doch einfach aus!
Hinweis: Du musst dir das binär, also auf Bitebene ansehen.
Die Fragestellung lautet: wenn du eine Binärzahl hast
die eine 2-er Potenz ist ( 1 << x liefert logischerweise
immer eine 2-er Potenz) und dann 1 davon abziehst, wie
sieht dann das Ergebnis aus, welchem Muster folgt es?
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.