Bitmaske

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche

In der Informatik bezeichnet eine Bitmaske eine mehrstellige Binärzahl, mit der Informationen aus einer anderen Binärzahl gelesen oder gespeichert werden können.

Methoden[Bearbeiten]

Bit auslesen[Bearbeiten]

Beispiel für 1-Bit:

    01001011 Information
AND 00001000 Bitmaske
-------------
=   00001000 Ergebnis

Beispiel für 0-Bit:

    01001011 Information
AND 00000100 Bitmaske
-------------
=   00000000 Ergebnis

Mit einer einfachen Bedingung kann nun auf das Bit überprüft werden:

 IF Ergebnis == 0
 THEN "Bit ist 0"
 ELSE "Bit ist 1"

0-Bit setzen[Bearbeiten]

NOT 00001000 Bitmaske
-------------
=   11110111 invertierte Bitmaske
    01001011 Information
AND 11110111 invertierte Bitmaske
-------------
=   01000011 Ergebnis

1-Bit setzen[Bearbeiten]

    01001011 Information
OR  00000100 Bitmaske
-------------
=   01001111 Ergebnis

Bit umschalten (toggle)[Bearbeiten]

    01001011 Information
XOR 00000110 Bitmaske
-------------
=   01001101 Ergebnis

Ein XOR Beispiel:

A   XOR B
10  XOR 255 = 245
245 XOR 255 = 10

Bitmasken zusammenfassen[Bearbeiten]

    00000001 Bitmaske1
OR  00000010 Bitmaske2
-------------
    00000011 zusammengefasste Bitmaske

Bitmaske erstellen[Bearbeiten]

Die meisten Programmiersprachen unterstützen logisches Schieben, womit sehr effizient Masken mit nur einem Bit erstellt werden können. Im folgenden Beispiel wird eine Bitmaske mit einem gesetzten Bit an der vierten Position (00010000) erstellt.

 unsigned int bitmask = 1 << 4; // bitmask auf 00010000 setzen

Wenn die Bitmaske jedoch bereits vor der Programmausführung bekannt ist und der Compiler keine Konstantenfaltung unterstützt, wäre es effizienter, die Bitmaske als Konstante zu definieren.

Liste von 16 Bits in Hexadezimalschreibweise[Bearbeiten]

 #define Bitmask01    0x00000001
 #define Bitmask02    0x00000002
 #define Bitmask03    0x00000004
 #define Bitmask04    0x00000008
 #define Bitmask05    0x00000010
 #define Bitmask06    0x00000020
 #define Bitmask07    0x00000040
 #define Bitmask08    0x00000080
 #define Bitmask09    0x00000100
 #define Bitmask10    0x00000200
 #define Bitmask11    0x00000400
 #define Bitmask12    0x00000800
 #define Bitmask13    0x00001000
 #define Bitmask14    0x00002000
 #define Bitmask15    0x00004000
 #define Bitmask16    0x00008000

Praktischer Einsatz[Bearbeiten]

Speichereinsparung[Bearbeiten]

Da bei der Programmierung aufgrund des internen Computeraufbaus für eine Variable immer mindestens ein Byte benutzt werden muss (auch für Wahrheitswerte), wäre es ineffizient, für jede Information die nur ein Bit benötigt, ein komplettes Byte zu verwenden. Mit einer Bitmaske können bis zu acht Bits in einem Byte angesprochen werden. Es werden in der Praxis jedoch meist nur logisch zusammengehörige Bits in einem Byte gespeichert (siehe Beispiel: benannte Flags). Die Speichereinsparung ist hauptsächlich in der Hardware-Programmierung oder bei Netzwerkprotokollen nötig, da dort Speicherplatz sehr rar ist. In der Anwendungsprogrammierung steht der Aufwand für die Einsparung meist in keinem sinnvollen Verhältnis zum Nutzen, da moderne Personal Computer über mehrere Gigabyte Arbeitsspeicher verfügen (Stand 2013).

Benannte Flags[Bearbeiten]

In OpenGL wird beispielsweise die Funktion glClear definiert, welche einen oder mehrere von vier Grafikpuffern löscht. Die Entwickler hätten nun vier Parameter definieren können, welche jeweils angeben ob der Grafikpuffer gelöscht werden soll oder nicht. Der Funktionsaufruf würde folgendermaßen aussehen:

 void glClear(1, 1, 0, 0); // Achtung! Diesen Funktionsaufruf gibt es nicht

Dies ist aber weder effizient, da vier Variablen übergeben werden müssen, noch sehr leserlich. Daher wurde in der gl.h für jeden Puffer ein sogenanntes benanntes Flag definiert:

 #define GL_DEPTH_BUFFER_BIT               0x00000100
 #define GL_ACCUM_BUFFER_BIT               0x00000200
 #define GL_STENCIL_BUFFER_BIT             0x00000400
 #define GL_COLOR_BUFFER_BIT               0x00004000

Und für die Funktion wurde nur ein einzelner Parameter definiert:

 void glClear(GLbitfield mask); // GLbitfield ist ein typedef auf unsigned int

Der Funktionsaufruf sieht nun folgendermaßen aus:

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Intern könnte die Funktion folgendermaßen aussehen:

 void glClear(GLbitfield mask) {
    if (mask & GL_COLOR_BUFFER_BIT) {
       // Clear color buffer
    }
    if (mask & GL_DEPTH_BUFFER_BIT) {
       // Clear depth buffer
    }
    if (mask & GL_ACCUM_BUFFER_BIT) {
       // Clear accumulation buffer
    }
    if (mask & GL_STENCIL_BUFFER_BIT) {
       // Clear stencil buffer
    }
 }

Bitfelder[Bearbeiten]

In der Programmiersprache C ist es zudem möglich, Bitfelder zu verwenden, die den direkten Zugriff auf einzelne Bits erlauben. Es ist jedoch zu beachten, dass der Code dadurch prozessorabhängig wird, da sie von Little- und Big-Endian-Architekturen beeinflusst werden.

 struct struct-type-name {
     type [name1] : length;
     type [name2] : length;
     //...
     type [nameN] : length;
 } variable-list;

In der Programmiersprache C# ist es mittels der Flags Attribute möglich, eine Enumeration als Bitfeld zu deklarieren. Außerdem stellt das .NET Framework die Datenstruktur BitArray zur Verfügung, welche einzelne Bits kompakt speichert und boolesche Operationen ermöglicht.

Weitere Anwendungsbeispiele[Bearbeiten]

Siehe auch[Bearbeiten]