Verwendung von Bitmask in C++

Jinku Hu 12 Oktober 2023
  1. Verwenden von struct zum Definieren von Bitmasken und Implementieren von Datumsobjekten in C++
  2. Benutzen Sie struct und union, um eine Bitmaske zu definieren und ein Datumsobjekt in C++ zu implementieren
  3. Verwenden von std::bitset zum Definieren von Bitmasken in C++
Verwendung von Bitmask in C++

In diesem Artikel werden mehrere Methoden zur Verwendung von Bitmasken in C++ vorgestellt.

Verwenden von struct zum Definieren von Bitmasken und Implementieren von Datumsobjekten in C++

struct ist eine beliebte Datenstruktur in C++. Außerdem unterscheidet sie sich nur geringfügig von der class im Gegensatz zur Sprache C. In diesem Fall müssen wir nur struct mit mehreren Datenmitgliedern definieren, aber es wird eine neue Notation : nach jedem Variablennamen und einer angegebenen Ganzzahl verwendet. Wie im Beispielcode gezeigt, haben wir ein struct mit Datenmitgliedern vom Typ uint32_t deklariert, und die Summe der Zahlen auf der rechten Seite ist 32. Diese Konstruktion impliziert, dass das struct die Größe eines einzelnen uint32_t-Datentyps im Speicher belegt und der Anwender auf seine Bitfeldbereiche (23:5:4) separat zugreifen kann.

Diese Methode wird meist verwendet, um Speicherplatz für Datenstrukturen zu sparen, die in ähnliche structs gequetscht werden könnten. Es ist auch eine der üblichen Methoden, um in der Programmiersprache C++ auf kleinere Daten als ein Byte zuzugreifen. Beachten Sie, dass das erste Mitglied year nur ganzzahlige Werte bis 223-1 aufnehmen kann und die anderen Mitglieder in ähnlicher Weise folgen.

#include <iostream>

using std::cout;
using std::endl;

struct {
  uint32_t year : 23;
  uint32_t day : 5;
  uint32_t month : 4;
} typedef Bitfield;

int main() {
  Bitfield date = {2020, 13, 12};

  cout << "sizeof Bitfield: " << sizeof(date) << " bytes\n";
  cout << "date: " << date.day << "/" << date.month << "/" << date.year << endl;

  return EXIT_SUCCESS;
}

Ausgabe:

sizeof Bitfield: 4 bytes
date: 13/12/2020

Benutzen Sie struct und union, um eine Bitmaske zu definieren und ein Datumsobjekt in C++ zu implementieren

Die vorherige Methode ist eine ausreichende und korrekte Art, Bitmaske zu implementieren. Sie hat jedoch einen Nachteil - der Zugriff auf und die Zuweisung von Werten an Mitglieder nimmt relativ mehr Zeit in Anspruch als Operationen an eingebauten Typen. Dies kann durch die Implementierung eines Objekts vom Typ union gelöst werden, das aus einem struct und einer einzelnen Variablen vom eingebauten Typ besteht. Beachten Sie, dass das Layout von struct das gleiche ist, das wir in der vorherigen Methode konstruieren würden. In diesem Fall ist der Unterschied die Variable uint32_t ydm, die die gleiche Größe wie das struct einnimmt.

Die Idee ist, die Datenmitglieder schneller zu initialisieren/ihren Werten zuzuweisen. Wir konstruieren nämlich eine Ganzzahl mit bitweisen Operationen, die genau dem Layout der Bits entsprechen, wenn sie im struct gespeichert sind, und weisen sie dann einem einzelnen uint32_t-Mitglied zu. Das spart Zeit, wenn man nur einmal auf die Daten zugreift, anstatt die gleiche Operation für jedes der drei Mitglieder zu wiederholen.

Bitweise Arithmetik ist relativ einfach; wir beginnen nämlich mit dem Wert des ersten Mitglieds im struct, der mit dem Ergebnis des nächsten Mitglieds, das um die Anzahl der Bits, die das vorherige Mitglied belegt, nach links verschoben ist, ODER-verknüpft wird, und es folgt in ähnlicher Weise.

#include <iostream>

using std::cout;
using std::endl;

union BitfieldFast {
  struct {
    uint32_t year : 23;
    uint32_t day : 5;
    uint32_t month : 4;
  };
  uint32_t ydm;
};

int main() {
  BitfieldFast date_f{};
  date_f.ydm = 2020 | (13 << 23) | (12 << 28);

  cout << "sizeof BitfieldFast: " << sizeof(date_f) << " bytes\n";
  cout << "date: " << date_f.day << "/" << date_f.month << "/" << date_f.year
       << endl;

  return EXIT_SUCCESS;
}
sizeof BitfieldFast: 4 bytes
date: 13/12/2020

Verwenden von std::bitset zum Definieren von Bitmasken in C++

std::bitset ist eine Standardbibliotheksfunktion, die die Klasse zum Speichern der binären Maskendaten enthält. bitset hat mehrere nützliche Manipulationsfunktionen eingebaut, und die Deklaration ist recht mühelos. Es kann mit einem binären String-Wert oder mehreren Zahlenwerten initialisiert werden. Bitweise Operationen sind eingebaute Methoden und können mit traditionellen Operatoren, die überladen sind, aufgerufen werden. Beachten Sie, dass die Methode reset das Bitset, von dem sie aufgerufen wird, permanent verändert.

#include <bitset>
#include <iostream>

using std::cout;
using std::endl;

int main() {
  std::bitset<16> bs1("1100100011110010");
  std::bitset<16> bs2(0xfff0);
  cout << "bs1        : " << bs1 << endl;
  cout << "bs2        : " << bs2 << endl;
  cout << "NOT bs1    : " << ~bs1 << endl;
  cout << "bs1 AND bs2: " << (bs1 & bs2) << endl;
  cout << "bs1 reset  : " << bs1.reset() << endl;

  return EXIT_SUCCESS;
}

Ausgabe:

bs1        : 1100100011110010
bs2        : 1111111111110000
NOT bs1    : 0011011100001101
bs1 AND bs2: 1100100011110000
bs1 reset  : 0000000000000000
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook