41 Stimmen

Verwendung der bitweisen Operatoren, um mehrere Werte in einen int zu packen

Low-Level-Bit-Manipulation war noch nie meine Stärke. Ich werde einige Hilfe beim Verständnis der folgenden Anwendungsfall der bitweisen Operatoren zu schätzen wissen...

int age, gender, height, packed_info;

. . .   // Assign values 

// Pack as AAAAAAA G HHHHHHH using shifts and "or"
packed_info = (age << 8) | (gender << 7) | height;

// Unpack with shifts and masking using "and"
height = packed_info & 0x7F;   // This constant is binary ...01111111
gender = (packed_info >> 7) & 1;
age    = (packed_info >> 8);

Ich bin mir nicht sicher, was dieser Code bewirkt und wie er funktioniert. Warum wird die magische Zahl 0x7F verwendet? Wie wird das Packen und Entpacken bewerkstelligt?

Quelle

2voto

Anarchofascist Punkte 462

Der Operator für die Linksverschiebung bedeutet "Multiplizieren mit zwei, so oft". Im Binärsystem ist das Multiplizieren einer Zahl mit zwei dasselbe wie das Hinzufügen einer Null auf der rechten Seite.

Der rechte Shift-Operator ist das Gegenteil des linken Shift-Operators.

Der Pipe-Operator ist "oder", d. h. er legt zwei Binärzahlen übereinander, und wenn in einer der beiden Zahlen eine 1 enthalten ist, ist das Ergebnis in dieser Spalte eine 1.

Extrahieren wir also die Operation für packed_info:

// Create age, shifted left 8 times:
//     AAAAAAA00000000
age_shifted = age << 8;

// Create gender, shifted left 7 times:
//     0000000G0000000
gender_shifted = gender << 7;

// "Or" them all together:
//     AAAAAAA00000000
//     0000000G0000000
//     00000000HHHHHHH
//     ---------------
//     AAAAAAAGHHHHHHH
packed_info = age_shifted | gender_shifted | height;

Und das Auspacken ist das Gegenteil.

// Grab the lowest 7 bits:
//     AAAAAAAGHHHHHHH &
//     000000001111111 =
//     00000000HHHHHHH
height = packed_info & 0x7F;

// right shift the 'height' bits into the bit bucket, and grab the lowest 1 bit:
//     AAAAAAAGHHHHHHH 
//   >> 7 
//     0000000AAAAAAAG &
//     000000000000001 =
//     00000000000000G
gender = (packed_info >> 7) & 1;

// right shift the 'height' and 'gender' bits into the bit bucket, and grab the result:
//     AAAAAAAGHHHHHHH 
//   >> 8
//     00000000AAAAAAA
age    = (packed_info >> 8);

1voto

Vlad Punkte 34235

Sie können den Ausdruck x & mask als eine Operation, die aus x die Bits, die nicht vorhanden sind (d. h. den Wert 0 haben) in mask . Das bedeutet, packed_info & 0x7F entfernt von packed_info alle Bits, die oberhalb des siebten Bits liegen.

Beispiel: wenn packed_info es 1110010100101010 im Binärformat, dann packed_info & 0x7f wird

1110010100101010
0000000001111111
----------------
0000000000101010

Also, in height erhalten wir die unteren 7 Bits von packed_info .

Als Nächstes verschieben wir die gesamte packed_info durch 7, auf diese Weise entfernen wir die Informationen, die wir bereits ausgelesen haben. Wir erhalten also (für den Wert aus dem vorherigen Beispiel) 111001010 Das Geschlecht wird im nächsten Bit gespeichert, also mit dem gleichen Trick: & 1 wir extrahieren nur dieses Bit aus der Information. Der Rest der Information ist im Offset 8 enthalten.

Auch das Einpacken ist nicht kompliziert: Sie nehmen age und verschieben Sie es um 8 Bits (Sie erhalten also 1110010100000000 von 11100101 ), verschieben Sie die gender durch 7 (Sie erhalten also 00000000 ), und nehmen Sie die Höhe (unter der Annahme, dass sie in die unteren 7 Bits passen würde). Dann fügen Sie alle diese Daten zusammen:

1110010100000000
0000000000000000
0000000000101010
----------------
1110010100101010

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X