Einleitung
Bitoperationen
Schiebeoperationen
Kurzschreibweisen
Beispiel und Übung
Bisher wurden Operationen nur auf Bytes oder einem Vielfachen davon (char, short, int, long Variablen bzw. Konstanten) ausgeführt. C++ bietet jedoch auch die Möglichkeit, einzelne Bits von Ganzzahlen mithilfe von Bitoperationen zu beeinflussen.
Da Bitoperationen nur auf Ganzzahlen zulässig sind, können mit ihnen (unter der Annahme, dass char gleich 8 Bits enthält) sizeof(char)*8, sizeof(short)*8, sizeof(int)*8 oder sizeof(long)*8 Bits gleichzeitig beeinflusst werden, abhängig davon, ob die Bitoperation auf einen char, short, int oder long Datentyp angewandt wird. Bis auf den Bitoperator 'rechts schieben' arbeiten alle Bitoperatoren vorzeichenunabhängig, d.h. sie wirken auf signed und unsigned Daten gleich.
|
|
Bevor es gleich mit den Operationen los geht, nochmals zur Wiederholung die binäre Darstellung von Ganzzahlen anhand einer unsigned char Variablen (Annahme: char gleich 8 Bits).
| Wert 10 | => hex: 0x0A | => binär: 0000 1010 |
| Wert: 240 | => hex: 0xF0 | => binär: 1111 0000 |
| Wert: 131 | => hex: 0x83 | => binär: 1000 0011 |
Um einzelne Bits einer Ganzzahl zu beeinflussen, stehen die folgenden Bitoperationen zur Verfügung:
Zwei Operanden werden durch den Operator & UND-verknüpft.
| ergebnis = operand1 & operand2; |
Die UND-Verknüpfung liefert als Ergebnis nur an den Stellen ein 1-Bit, an denen beiden Operanden ein 1-Bit besitzen.
Beispiel:
| operand1 | operand2 | ergebnis | ||
| 0x26 (0010 0110) | & | 0x23 (0010 0011) | => | 0x22 (0010 0010) |
| 0x45 (0100 0101) | & | 0x0F (0000 1111) | => | 0x05 (0000 0101) |
Zwei Operanden werden durch den Operator | ODER-verknüpft.
| ergebnis = operand1 | operand2; |
Die ODER-Verknüpfung liefert als Ergebnis an den Stellen ein 1-Bit, an denen mindestens einer der Operanden ein 1-Bit besitzt.
Beispiel:
| operand1 | operand2 | ergebnis | ||
| 0x26 (0010 0110) | | | 0x23 (0010 0011) | => | 0x27 (0010 0111) |
| 0x45 (0100 0101) | | | 0x0F (0000 1111) | => | 0x4F (0100 1111) |
Zwei Operanden werden durch den Operator ^ EXKLUSIV-ODER-verknüpft.
| ergebnis = operand1 ^ operand2; |
Die EXKLUSIV-ODER Verknüpfung liefert als Ergebnis an den Stellen ein 1-Bit, an denen beide Operanden unterschiedliche Bits besitzen
|
|
Beispiel:
| operand1 | operand2 | ergebnis | ||
| 0x26 (0010 0110) | ^ | 0x23 (0010 0011) | => | 0x05 (0000 0101) |
| 0x45 (0100 0101) | ^ | 0x0F (0000 1111) | => | 0x4A (0100 1010) |
Für die Invertierung aller Bits eines Operanden wird der Operator ~ verwendet.
| ergebnis = ~operand; |
Das Ergebnis enthält an den Stellen ein 1-Bit, an denen der Operand ein 0-Bit besitzt und umgekehrt. Man bezeichnet diese Operation auch als Bildung des 1er-Komplements.
Beispiel:
| operand | ergebnis | |
| ~0x26 (0010 0110 | => | 0xD9 (1101 1001) |
| ~0x45 (0100 0101) | => | 0xBA (1011 1010) |
Außer den Bitoperationen stellt C++ auch noch Operatoren zur Verfügung, um die Bits einer Ganzzahl um eine bestimmte Anzahl von Positionen nach links oder rechts zu schieben.
Die Bits eines Operanden können mithilfe des Operators << um eine definierte Anzahl von Bits nach links geschoben werden.
| ergebnis = operand << bitzahl; |
Die rechts frei werdenden Bits werden mit 0 aufgefüllt und Überläufe werden verworfen.
Beispiel:
| operand1 | bitzahl | ergebnis | ||
| 0x26 (0010 0110) | << | 2 | => | 0x98 (1001 1000) |
| 0x45 (0100 0101) | << | 4 | => | 0x50 (0101 0000) |
Die Bits eines Operanden können mithilfe des Operators >> um eine definierte Anzahl von Bits nach rechts geschoben werden.
| ergebnis = operand >> bitzahl; |
Ist die Ganzzahl vorzeichenlos (unsigned), werden die links frei werdenden Bits mit 0 aufgefüllt. Bei positiven vorzeichenbehafteten Zahlen werden die frei werdenden Bits ebenfalls mit 0 aufgefüllt.
|
|
Beispiel:
| operand1 | bitzahl | ergebnis | ||
| 0x26 (0010 0110) | >> | 2 | => | 0x09 (0000 1001) |
| 0x45 (0100 0101) | >> | 4 | => | 0x04 (0000 0100) |
Genauso wie bei den Grundrechenoperationen, stehen auch für die Bit- und Schiebeoperationen entsprechende Kurzschreibweisen zur Verfügung, die in der nachfolgenden Tabelle aufgeführt sind.
| x &= y | x = x & y |
| x |= y | x = x | y |
| x ^= y | x = x ^ y |
| x <<= y | x = x << y |
| x >>= y | x = x >> y |
|
|
High-Byte von 0xaa55: 0xaa |
|
// Beispiel zu Bitoperationen // Zuerst Dateien iostream und iomanip einbinden #include <iostream> #include <iomanip> using std::cout; using std::endl; // Variable für Zerlegung definieren unsigned short var = 0xAA55; // main() Funktion int main () { // Ausgabe auf hex umstellen mit Angabe der Zahlenbasis cout << std::hex << std::showbase; // High-Byte der Variablen ausgeben cout << "High-Byte von " << var << ": " << (var>>8) << endl; // Low-Byte der Variablen ausgeben cout << "Low-Byte von " << var << ": " << (var&0xFF) << endl; // Ausgabe wieder auf dezimal zurückstellen cout << std::dec; // 2er Potenzen ausgeben cout << "2 hoch 0: " << (1<<0) << endl; cout << "2 hoch 1: " << (1<<1) << endl; cout << "2 hoch 2: " << (1<<2) << endl; cout << "2 hoch 3: " << (1<<3) << endl; // Zum Schluss eine Division durch 8 cout << "244/8: " << (244>>3) << endl; } |
Es ist eine short Variable shortVar und eine char Variable charVar zu definieren. Die short Variable ist mit 10 und die char Variable mit dem Hex-Wert 0x55 zu initialisieren.
Anschließend ist die char Variable charVar in binärer Darstellung (nur 0 und 1) auszugeben. Verwenden Sie dazu nur Bitoperationen.
Von der short Variablen shortVar ist zunächst das 1er-Komplement zu bilden und auszugeben. Addieren Sie zu dem so erhaltenen Ergebnis eins hinzu und geben das Ergebnis erneut aus. Welche Zahl erhalten Sie?
|
0x55 nach binär: 01010101 |