Hallo,
ich lege mir hier gerade die Karten, auf dem Papier weiß ich was ich
machen möchte aber es in C umzusetzen da stehe ich gerade auf dem
Schlauch.
Ich möchte eine bestimmte Anzahl von Bits maskieren die im
Programmablauf dynamisch ist und eben von 1-8 Bits sein kann.
Wie ich 3 Bits maskiert ist mir klar...
1
uint8_ta,b;
2
3
...
4
b=0b00001101;
5
a=b&0b00000111;
6
...
a sollte dann 0b00000101 sein...
Wie stelle ich das nun an wenn ich x Bit maskieren möchte?
Ergebniss soll dann sein das man per Parameter die Bits maskiert
GET_MASK_BITS(3); gibt nur die ersten 3 Bits zurück...
Macht man das mit einen switch/case Block?
Grüße AVRli...
Vielleicht habe ich mich auch unglücklich ausgedrückt, doch das was
holger beschrieben hat, ist das was ich gesucht habe. Das ganze habe ich
mir nun nochmal für die andere Richtung geschrieben...
AVRli schrieb:> Vielleicht habe ich mich auch unglücklich ausgedrückt,
Nein.
> doch das was> holger beschrieben hat, ist das was ich gesucht habe.
Das, was Johann und ich geschrieben haben, ist es dann auch. ;-)
Holger benutzt halt eine tabellenbasierten Ansatz, Johann und ich
einen arithmetischen. Die Tabelle ist schneller, braucht aber
bei größeren zulässigen Operanden schnell viel Platz.
Habe mir das nun nochmal angesehen und auch für die LSB Variante
verstanden wie der rechnerische Weg ist... das ist auch recht elegant!!!
Ich habe es auf dem ersten Blick nur so gesehen das man das einzelne Bit
zurück bekommt.
Durch Euren Schuppser nun erkannt das durch das -1 dann die maskierten
die richtige Rückgabe sind... gut gut!
Habe mich dann für diesen Weg entschieden da ich den RAM noch brauche...
Wieder was gelernt! ;-)
Aber ganz ehrlich die andere Richtung bekomme ich so nicht hin... ich
habe wohl meine Schwierigkeiten mit der Bit- Manipulation...
Gruß AVRli...
AVRli schrieb:> Aber ganz ehrlich die andere Richtung bekomme ich so nicht hin...
kleiner Tip.
Wenn du in einem Byte nur die untersten 5 Bits auf 1 hast, dann sind
logischerweise die obersten 3 Bits auf 0 (weil 5 + 3 wieder die 8 Bits
in einem Byte ergeben).
Dreht man dann in dem so erhaltenen Byte die Bits einfach alle um, dann
hat man ein Byte, bei dem die obersten 3 Bits auf 1 sind und die unteren
5 Bits auf 0.
Um also ein Byte zu erhalten, bei dem die obersten n Bits auf 1 sind,
genügt es sich ein Byte zu machen, bei dem die unteren (8-n)Bits auf 1
sind und dann einfach alle Bits umzudrehen.
Und wie man sich ein Byte macht, bei dem die unteren m Bits auf 1 sind,
dafür hast du ja schon eine Funktion :-)
Bsp. Du brauchst ein Byte, bei dem die oberen 2 Bits auf 1 sind.
Zu erzeugen ist also 0b11000000
------------------------------------------------------
Dazu erzeugst du dir ein Byte,
bei dem die unteren 6 Bits auf 1 sind 0b00111111
und drehst alle Bits um 0b11000000
Vielen Dank an Euch!
Als erstes habe ich versucht mit einer "Spiegelung zum Erfolg zu kommen
doch das war nichts... für Euch sicher logisch, ich vermute es geht
nicht weil man bei 8 Bit theoretisch 9 braucht und deshalb bei 8 eine 0
zurück kommt.
1
#define GET_MASK_BIT_MSB(N) (~((1u << (N)) -1))
Dann habe ich den Vorschlag von "bit schieber" probiert, den habe ich
auch verstanden, doch da muss mana auch erstmal drauf kommen... ;-)
Many Thanks!!! AVRli...
Ja das funktioniert nun... mit bit schieber sein #define ging es auch
nicht so ganz... warum kann ich nicht erklären... mit der Zeile klappt
es wie ich es erwartet habe doch wenn ich ganz ehrlich bin grübel ich
noch über den Wert
-1u
heißt -1 nicht das es signed ist und das u das es unsigned sein
soll... grübel
Gruß AVRli...
-1u ist ein unsigned, der alle Bits gesetzt hat. Alternativ geht auch
UINT_MAX aus limits.h oder, falls 16-Bit int, UINT16_MAX aus stdint.h
Um zB eine Maske zu bekommen, die jedes 3. Bit gesetzt hat, kann man
einfach
Vielen Dank für die Erklärung!
Ich sehe das ich es viel umständlicher lösen würde, wenn ich das mal
benötigen würde. Ich hätte mir ein Byte genommen und mein Bitmuster mit
Zählern rein geschoben. Das es auch so geht war mir nicht klar.
Wie man auf die passenden Teilungswerte kommt habe ich nach langen
probieren auch herausgefunden.
jedes 5 Bit gesetzt...
AVRli schrieb:> Nur ganz ehrlich... nicht lachen Warum das so klappt ist mir ein> Rätsel... :-D
Es beruht auf folgender Faktorisierung:
Oben ist b=2, d.h. es ist für Zahlen in Binärdarstellung, aber die
Faktorisierung geht genauso für alle anderen b-ären Darstellungen.
Z.B ist 111111 immer durch 111 und duch 11 teilbar, unabhängig vom
Zahlensystem, in dem diese Zahlen dargestellt sind.
Johann L. schrieb:> unsigned long mask_jedes_3te_bit = -1ul / 7; // 0x24924924
Hm, wobei mich das -1u oder -1ul auch eher irritieren würde.
Warum nicht 0xffff oder 0xffffffff etc. je nach Anzahl Bits, dann ist
sofort klar dass es ein uint16_t/uint32_t mit allen Bits auf 1 gesetzt
ist.
asdf schrieb:> Johann L. schrieb:>> unsigned long mask_jedes_3te_bit = -1ul / 7; // 0x24924924>> Hm, wobei mich das -1u oder -1ul auch eher irritieren würde.>> Warum nicht 0xffff oder 0xffffffff etc. je nach Anzahl Bits, dann ist> sofort klar dass es ein uint16_t/uint32_t mit allen Bits auf 1 gesetzt> ist.
Da muss man aber erst die 'f's nachzählen. Bei 16 Bit ist das noch
leicht, bei 32 Bit schon etwas ungemütlich und bei 64 Bit ziemlich
fehlerträchtig ;-)
Wenn dich nur die Negation des unsigned-Werts stört, kannst du auch