mehrer Bits verschieben

Gast #970141
Hallo,

hab eine einfache Frage, komme aber gerade nicht selber drauf.

Ich möchte die ersten 4 Bit eines 8 Bitsignales um 4 nach links 
verschieben.

Einzelne Bits in C kann man ja wie folgt verschieben:

Signal[0] << 4; // 1.Bit um 4 nach links verschoben

Nun möchte ich aber die 4.Bit mit einmal verschieben, gibts da eine 
einfache Möglichkeit oder muss ich jedes Bit einzeln verschieben?

Danke
Mit einem Shift werden immer alle Bits in der betreffenden Variable 
verschoben. Die Shift-Operatoren besitzen 2 Argumente: dasjenige links 
vom Operator ist die Variable, die geschoben werden soll und rechts 
steht die Anzahl der Stellen, um die geschoben werden soll.
Ach ja, wenn Du meinen solltest, mit Signal[0] würdest Du auf ein Bit 
einer Variablen namens Signal zugreifen, dann täuschst Du Dich! 
Signal[0] liefert das erste Element eines Arrays (von Variablen des Typs 
XXX). Wenn Signal ein Array von int ist (also z.B.
1
 int Signal[Array_Laenge];
), dann ist Signal[0] auch ein int mit mindestens 16 Bit. 
Dementsprechend werden z.B. bei
1
Irgendwas = Signal[0] << 4;
auch alle 16 Bit geschoben.
Gast
Ok,

dann ist es doch nicht so einfach.

Wie kann ich denn die ersten 4 Bit aus dem Signal extrahieren, um diese 
zu verschieben?

Ich muss nur, die ersten 4 verschieben und nicht alle.
Gast
Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste nach
1
variable = (variable & 0x0F) << 4;
 z.B. aus 1001 0110 => 1111 0110 werden?
Gast
Je nach Variablentypus ist die Maskiererei auch Käse, weil, wenn ich in 
nem Byte die unteren vier Bits um vier Stellen nach links verschiebe...

Achso, und Schiebereien um mehrere Positionen mag der GCC+AVR im Übrigen 
garnicht, und erst recht nicht, wenn die Anzahl der zu verschiebenden 
Stellen noch variabel ist:
1
uint8_t a, b, i;
2

3
a = b << 1; /* schnell */
4
a = b << 4; /* auch noch schnell, weil swap+and in Assembler */
5
a = b << 3; /* nich-sooooo-gut, aber immer noch schnell */
6
a = b << i; /* Bullshit, weil Schleife in Assembler */
@auf_den_Schlauch_steher (Gast)

>Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste

>nachvariable = (variable & 0x0F) << 4;

> z.B. aus 1001 0110 => 1111 0110 werden?

Nö.

Erster Schritt, Maskieren in der Klammer

(variable & 0x0F) = 1001 0110 & 0000 1111 = 0000 0110

Zweiter Schritt, nach Links verschieben, es wird mit Null aufgefüllt

() <<4 = 0000 0110 << 4 = 0110 0000

MFG
Falk
auf_den_Schlauch_steher wrote:
> Wenn ich das richtig mit der Bitmanipulation verstanden habe müsste nach
>
1
variable = (variable & 0x0F) << 4;
 z.B. aus 1001 0110 =>
> 1111 0110 werden?

Natürlich nicht.

Nach dem Maskieren ist es 0000 0110 und dann nach dem Schieben um 4
0110 0000.


Peter
Gast
> Nach dem Maskieren ist es 0000 0110 und dann nach dem Schieben um 4 0110 0000.

richtig.
warum also die maskiererei?

variable <<= 4;

macht das gleiche.
Gast
Christian R. wrote:
> Das ist aber dann Compiler-abhängig, oder? Also ich meine, der MSPGCC
> maskiert bei Bedarf selbst, bevor er rotiert....hab das mal im Listung
> gesehn.

Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard 
festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
Persönliche Seite
Sven Pauli wrote:
> Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard
> festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
Sicher??
Also "mein" Standard (C99) sagt:
links shift: es wird IMMER mit 0 aufegführt.
rechts shift: unsinged wird mit 0 aufgefüllt, signed wird mit dem 
sign-bit (negativ = 1, postiv = 0) aufgefüllt!
Gast
Läubi Mail@laeubi.de wrote:
> Sven Pauli wrote:
>> Rotieren geht in C nicht direkt. Und beim Schieben ists im Standard
>> festgelegt, dass links bzw. rechts Nullen nachgeschoben werden.
> Sicher??
Ja, sicher...wobei ich jetzt unsigned vorausgesetzt hab :-/ Ansonsten 
sinds halt VZ-Bits, jubb.
Gast
> Hallo, hab eine einfache Frage, komme aber gerade nicht selber drauf.
> Ich möchte die ersten 4 Bit eines 8 Bitsignales um 4 nach links verschieben.

die lösung heisst

unsigned char signal;
signal <<= 4;

over and out.
ich habe das gefühl, dass der OP genau das erreichen will, was er in der 
Zwischenfrage gestellt hat:
0100 1001     solll nach der operation zu 1101 ?(0000)? werden.
Das funktioniert wie folgt:

uint8_t a = 0b01001001;
a |= (a << 4);

(falls gewünscht low nibble auf 0 setzen:)
a &= 0xF0;

Ich weiß nicht, was der Compiler daraus macht. aber im Assembler würde 
ich das so lösen:
rE -> Eingangsregister (high register)
rT -> temporäres register

mov rT, rE
swap rT
or rE, rT
andi rE, 0xF0

das gewünschte Ergebnis liegt dann wieder in rE.
Matze
Gast
Hi,

das von Matze scheint das zu seien was ich brauche. Denn nachdem ich die 
ersten 4 Bit verschoben habe, muss ich sie wieder mit den letzten 4.Bit 
addieren. Sry, dass ich das nicht gleich geschrieben habe, dachte nicht 
das es bei der schiebe Operation von belangen ist.

Ich werde das ganze mal testen und schauen ob es das gewünschte Ergebnis 
liefert.
Du musst dich mal bitte auch weiterhin etwas genauer ausdrücken. In 
deinem letzten Post schreibst du:
Denn nachdem ich die
ersten 4 Bit verschoben habe, muss ich sie wieder mit den letzten 4.Bit
addieren.

2 Sachen: a) "den letzten 4. bit" gibt es nicht. der Punkt hinter der 4 
bedeuted VIERTES Bit und bezieht sich somit auf 1 Bit. Kann eventuell in 
anderer Formulierung zu Unklarheiten führen.

b) Die lieben Grundrechenarten eines Prozessors. Du sprichst hier von 
"addieren". Da besteht ein kleiner aber feiner Unterschied zum Oder:

0b011001011
0b101000101 seien unsere 2 Bytes. Verodert ergibt sich:

0b111001111    addiert ergibt sich aber:
0b000010000 + carry bit set -> 9 bit ergebnis 0b1000010000

wahh ich seh gerade ich hab versehtnlich 9 statt 8 Bits aufgeschrieben, 
aber das Additionsbeispiel ist gerade so toll, ich belasse es einfach 
mal dabei.

Matze (Der eigentlich gerade an seinem Artikel arbeiten sollte, da in 
nichtmal mehr 10 Stunden die Deadline vorbei ist...)
Gast
Hallo.
Ich hab auch mal eine Frage zum Bitshifting.

Hab eine 16Bit-Variable aus der ein 12Bit-Wert extrahiert werden 
soll.Dieser Wert setzt sich aus den Bits 0 bis 11 zusammen.Wie bekomme 
ich da den Wert nun aus den 16Bit heraus,mit Vorzeichen?!
D.h. in der Spanne von -2046 bis 2045?

hier der Code (beispielhaft):

signed int variable1 = 0x2DAA;

variable1 <<= 4; // Schiebe um 4 Stellen nach links

Der Wert von variable1 bewegt sich aber nun nicht im Bereich von -2046 
bis 2045. Wie bekomm ich das hin?
Denny S. schrieb:
> Hallo!
>
> Ich habe gerade auch ein paar Probleme mit dem Bit bestimmen.
>
> Ich habe ein uint16_t und will nun nur die unteren 3 Bits wissen.
> Wie mache ich das?

Indem du eine Maske benutzt, in der die unteren 3 Bits 1 sind und alle 
anderen 0.


  Ergebnis = Variable & 0x0007;

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

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.