Bitfeld - Bit field

Ein Bitfeld ist eine Datenstruktur, die aus einem oder mehreren benachbarten Bits besteht, die zugewiesen wurden, um eine Folge von Bits zu halten , die so gespeichert sind, dass jedes einzelne Bit oder jede Bitgruppe innerhalb der Gruppe gesetzt oder untersucht werden kann. Ein Bitfeld wird am häufigsten verwendet, um ganzzahlige Typen bekannter fester Bitbreite darzustellen .

Die Bedeutung der einzelnen Bits innerhalb des Feldes wird vom Programmierer bestimmt; zum Beispiel wird das erste Bit in einem Bitfeld (an der Basisadresse des Felds angeordnet ) manchmal verwendet, um den Zustand eines bestimmten Attributs zu bestimmen, das dem Bitfeld zugeordnet ist.

Innerhalb von CPUs und anderen Logikvorrichtungen werden üblicherweise "Flags" genannte Sammlungen von Bitfeldern verwendet, um das Ergebnis bestimmter Operationen zu steuern oder anzuzeigen. Prozessoren haben ein Statusregister , das aus Flags besteht. Kann beispielsweise das Ergebnis einer Addition nicht im Ziel dargestellt werden, wird ein arithmetischer Überlauf gesetzt. Die Flags können verwendet werden, um nachfolgende Operationen, wie z. B. bedingte Sprungbefehle , zu entscheiden . Beispielsweise führt ein (Jump if Equal)-Befehl in der x86-Assemblersprache zu einem Sprung, wenn das Z-Flag (Null) durch eine vorherige Operation gesetzt wurde. JE ...

Ein Bitfeld unterscheidet sich von einem Bitarray dadurch, dass letzteres verwendet wird, um einen großen Satz von Bits zu speichern, die durch ganze Zahlen indiziert sind, und oft breiter ist als jeder ganzzahlige Typ, der von der Sprache unterstützt wird. Bit - Felder, auf der anderen Seite, passen normalerweise in einem Maschinenwort , und die Bezeichnung von Bits unabhängig von ihrem numerischen Index.

Implementierung

Bitfelder können verwendet werden, um den Speicherverbrauch zu reduzieren, wenn ein Programm eine Reihe von Integer-Variablen erfordert, die immer niedrige Werte haben. Zum Beispiel erfordert das Speichern eines ganzzahligen Wertes in vielen Systemen zwei Byte (16 Bit) Speicher; manchmal benötigen die zu speichernden Werte tatsächlich nur ein oder zwei Bits. Wenn sich mehrere dieser winzigen Variablen ein Bitfeld teilen, ermöglicht dies ein effizientes Packen von Daten in den Speicher.

In C und C++ können systemeigene implementierungsdefinierte Bitfelder mit unsigned int, signed int oder (in C99:) _Bool erstellt werden. In diesem Fall kann der Programmierer für ein Bitfeld eine Struktur deklarieren, die mehrere Unterfelder beschriftet und die Breite bestimmt. Benachbart deklarierte Bitfelder des gleichen Typs können dann vom Compiler in eine reduzierte Anzahl von Wörtern gepackt werden, verglichen mit dem verwendeten Speicher, wenn jedes 'Feld' separat deklariert würde.

Bei Sprachen ohne native Bitfelder oder bei denen der Programmierer die Kontrolle über die resultierende Bitdarstellung haben möchte, ist es möglich, Bits innerhalb eines größeren Worttyps manuell zu manipulieren. In diesem Fall kann der Programmierer die Bits im Feld unter Verwendung von Kombinationen aus Maskierung und bitweisen Operationen setzen, testen und ändern .

Beispiele

Programmiersprache C

Ein Bitfeld in C und C++ deklarieren :

// opaque and show
#define YES 1
#define NO  0

// line styles
#define SOLID  1
#define DOTTED 2
#define DASHED 3

// primary colors
#define BLUE  0b100
#define GREEN 0b010
#define RED   0b001

// mixed colors
#define BLACK   0                    /* 000 */
#define YELLOW  (RED | GREEN)        /* 011 */
#define MAGENTA (RED | BLUE)         /* 101 */
#define CYAN    (GREEN | BLUE)       /* 110 */
#define WHITE   (RED | GREEN | BLUE) /* 111 */

const char* colors[8] = {"Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White"};

// bit field box properties
struct BoxProps
{
  unsigned int  opaque       : 1;
  unsigned int  fill_color   : 3;
  unsigned int               : 4; // fill to 8 bits
  unsigned int  show_border  : 1;
  unsigned int  border_color : 3;
  unsigned int  border_style : 2;
  unsigned char              : 0; // fill to nearest byte (16 bits)
  unsigned char width        : 4, // Split a byte into 2 fields of 4 bits
                height       : 4;
};

Das Layout von Bitfeldern in einem C structist implementierungsdefiniert . Für ein Verhalten, das über Compiler hinweg vorhersehbar bleibt, ist es möglicherweise vorzuziehen, Bitfelder mit einem Primitiv- und Bitoperator zu emulieren:

/* Each of these preprocessor directives defines a single bit,
   corresponding to one button on the controller.  
   Button order matches that of the Nintendo Entertainment System. */
#define KEY_RIGHT  0b00000001
#define KEY_LEFT   0b00000010
#define KEY_DOWN   0b00000100
#define KEY_UP     0b00001000
#define KEY_START  0b00010000
#define KEY_SELECT 0b00100000
#define KEY_B      0b01000000
#define KEY_A      0b10000000

int gameControllerStatus = 0;

/* Sets the gameControllerStatus using OR */
void KeyPressed( int key ) { gameControllerStatus |= key; }

/* Clears the gameControllerStatus  using AND and ~ (binary NOT)*/
void KeyReleased( int key ) { gameControllerStatus &= ~key; }

/* Tests whether a bit is set using AND */
int IsPressed( int key ) { return gameControllerStatus & key; }

Prozessorstatusregister

Ein Beispiel für ein Bitfeld- Statusregister ist im 6502- Prozessor enthalten. Jedes der einzelnen Bitfelder beschreibt Informationen über den Maschinenzustand:

  • N Negativ-Flag
  • V oVerflow-Flag
  • ungebraucht
  • B Break-Flag
  • D Dezimal-Flag
  • I Unterbrechungs-Deaktivierungs-Flag
  • Z Nullflagge
  • C Trageflagge

Diese Bits müssen nicht manipuliert werden, da sie vom Prozessor als Ergebnis einer Operation gesetzt werden und von explizit definierten Verzweigungsbefehlen wie zB BVC (Branch on oVerflow Clear), BEQ (Branch Z = 0) ausgewertet werden. Die Ausnahme ist das I-Flag, für das ein expliziter SEI-Befehl (SEt Interrupt Disable) vorliegt.

Extrahieren von Bits aus Flag-Wörtern

Eine Teilmenge von Flags in einem Flag-Feld kann durch UND-Verknüpfung mit einer Maske extrahiert werden . Eine große Anzahl von Sprachen unterstützt den Verschiebeoperator (<<), wobei 1 << nein einzelnes Bit an der n-ten Position ausgerichtet wird. Die meisten unterstützen auch die Verwendung des AND- Operators (&), um den Wert eines oder mehrerer Bits zu isolieren.

Wenn das Status-Byte von einem Gerät 0x67 ist und das 5. Flag-Bit Daten-Ready anzeigt. Das Maskenbyte ist . Die UND - Verknüpfung des Statusbytes 0x67 ( in binär) mit dem Maskenbyte 0x20 ( in binär) ergibt 0x20. Das bedeutet, dass das Flag-Bit gesetzt ist, dh das Gerät ist datenbereit. Wäre das Flag-Bit nicht gesetzt, wäre dieses zu 0 ausgewertet, dh es liegen keine Daten vom Gerät vor. 0110 01110010 0000

Um das n- te Bit einer Variablen v zu überprüfen , führen Sie die Operation aus:

bool nth_is_set = (v & (1 << n)) != 0;
bool nth_is_set = (v >> n) & 1;

Bits in Merkerwörtern ändern

Das Schreiben, Lesen oder Umschalten von Bits in Flags kann nur unter Verwendung der ODER-, UND- und NICHT-Operationen erfolgen - Operationen, die im Prozessor schnell ausgeführt werden können. Um ein Bit zu setzen, ODER das Statusbyte mit einem Maskenbyte. Alle im Maskenbyte oder Statusbyte gesetzten Bits werden im Ergebnis gesetzt.

Um ein Bit umzuschalten , XOR das Statusbyte und das Maskenbyte. Dadurch wird ein Bit gesetzt, wenn es gelöscht ist, oder ein Bit, wenn es gesetzt ist.

Siehe auch

Verweise

  1. ^ Penn Brumm; Don Brumm (August 1988). 80386 Assemblersprache: Ein komplettes Tutorial und eine Subroutinenbibliothek . McGraw-Hill School Education Group. P. 606. ISBN 978-0-8306-9047-3.
  2. ^ a b Steve Oualline (1997). Praktische C-Programmierung . "O'Reilly Media, Inc.". S.  403 –. ISBN 978-1-56592-306-5.
  3. ^ a b Michael A. Miller (Januar 1992). Die 68000 Mikroprozessorfamilie: Architektur, Programmierung und Anwendungen . Merrill. P. 323. ISBN 978-0-02-381560-7.
  4. ^ Ian Griffiths; Matthew Adams; Jesse Liberty (30. Juli 2010). Programmieren mit C# 4.0: Erstellen von Windows-, Web- und RIA-Anwendungen für das .NET 4.0 Framework . "O'Reilly Media, Inc.". S. 81–. ISBN 978-1-4493-9972-6.
  5. ^ Tibet Mimar (1991). Programmieren und Entwerfen mit der 68000-Familie: Einschließlich 68000, 68010/12, 68020 und 68030 . Lehrlingssaal. P. 275. ISBN 978-0-13-731498-0.
  6. ^ a b Prata, Stephen (2007). C-Primer plus (5. Aufl.). Indianapolis, Ind.: Sams. ISBN 978-0-672-32696-7.
  7. ^ Mark E. Daggett (13. November 2013). Experten-JavaScript . Apress. S. 68–. ISBN 978-1-4302-6097-4.
  8. ^ InCider . W. Grün. Januar 1986. p. 108.

Externe Links