bitweise Indizierung in C?
-
09-06-2019 - |
Frage
Ich versuche, eine Datenkompression Idee umzusetzen ich je hatte, und da ich es gegen einen großen Korpus von Testdaten vorzustellen, renne, hatte ich gedacht, es in C zu kodieren (I meist Erfahrung in Skriptsprachen haben wie Ruby und Tcl.)
durch die ‚Kuh‘ O'Reilly Suchen Bücher über C, merke ich, dass ich kann nicht einfach Index die Bits eines einfachen ‚char‘ oder ‚int‘ Typ Variable als Ich mag würde zu bitweise Vergleiche zu tun und Betreiber.
Bin ich in dieser Wahrnehmung zu korrigieren? Ist es vernünftig, für mich einen Aufzählungstyp zu verwenden, um ein Bit für die Darstellung (und eine Reihe von ihnen machen und zum Schreiben von Funktionen und von char zu konvertieren)? Wenn ja, wird ein solcher Typ und Funktionen in einer Standard-Bibliothek definiert schon irgendwo? Gibt es andere (bessere?) Ansätze? Gibt es ein Beispiel-Code irgendwo, dass jemand mir zeigen könnte?
Danke -
Lösung
Im Anschluss an was Kyle gesagt hat, können Sie einen Makro verwenden, um die harte Arbeit für Sie tun.
Es ist möglich.
So stellen Sie die n-te Bit, Verwendung oder:
x | = (1 << 5); // setzt den 6.-aus rechts
Um ein wenig, Verwendung klar und:
x & = ~ (1 << 5); // löscht 6.-von-rechts
Um ein Bit, verwendet XOR-Flip:
x ^ = (1 << 5); // Flips 6.-von-rechts
oder ...
#define GetBit(var, bit) ((var & (1 << bit)) != 0) // Returns true / false if bit is set
#define SetBit(var, bit) (var |= (1 << bit))
#define FlipBit(var, bit) (var ^= (1 << bit))
Dann können Sie es in Code wie verwenden:
int myVar = 0;
SetBit(myVar, 5);
if (GetBit(myVar, 5))
{
// Do something
}
Andere Tipps
Es ist möglich.
So stellen Sie die n-te Bit, Verwendung oder:
x |= (1 << 5); // sets the 5th-from right
Um ein wenig, Verwendung klar und:
x &= ~(1 << 5); // clears 5th-from-right
Um ein Bit, verwendet XOR-Flip:
x ^= (1 << 5); // flips 5th-from-right
Um den Wert eines Bits Verwendung Verschiebung zu erhalten und AND:
(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right
. Hinweis: Die Verschiebung nach rechts 5 ist der Wert entweder 0 oder 1, um sicherzustellen, Wenn Sie nur daran interessiert sind, 0/0 nicht, Sie ohne die Verschiebung erhalten, indem können
Um Zustand des Bits mit bestimmten Index Abfrage:
int index_state = variable & ( 1 << bit_index );
Bit einstellen:
varabile |= 1 << bit_index;
Bit neu zu starten:
variable &= ~( 1 << bit_index );
Einzelne Bits können wie folgt indiziert werden.
Definieren Sie eine Struktur wie diese:
struct
{
unsigned bit0 : 1;
unsigned bit1 : 1;
unsigned bit2 : 1;
unsigned bit3 : 1;
unsigned reserved : 28;
} bitPattern;
Wenn ich nun die einzelnen Bit-Werte eines var namens „Wert“, folgendermaßen Sie wissen wollen:
CopyMemory( &input, &value, sizeof(value) );
Um zu sehen, ob das Bit 2 hoch oder niedrig ist:
int state = bitPattern.bit2;
Hope, das hilft.
Versuchen Sie Bitfelder verwenden. Achten Sie darauf, die Umsetzung von Compiler variieren kann.
http://publications.gbdirect.co.uk/c_book/chapter6 /bitfields.html
Wenn Sie wollen Index ein wenig konnte man:
bit = (char & 0xF0) >> 7;
bekommt die msb eines char. Man könnte sogar die Verschiebung nach rechts verlassen und einen Test auf 0 tun.
bit = char & 0xF0;
Wenn das Bit gesetzt ist das Ergebnis> 0;
obviousuly, müssen Sie die Maske ändern, um verschiedene Bits zu erhalten (NB: 0 × F ist die Bitmaske, wenn es unklar ist). Es ist möglich, zahlreiche Masken beispiel zu definieren.
#define BIT_0 0x1 // or 1 << 0
#define BIT_1 0x2 // or 1 << 1
#define BIT_2 0x4 // or 1 << 2
#define BIT_3 0x8 // or 1 << 3
etc ...
Das gibt Ihnen:
bit = char & BIT_1;
Sie können diese Definitionen in den obigen Code verwenden Index ein Bit innerhalb entweder ein Makro oder eine Funktion erfolgreich.
ein wenig ein:
char |= BIT_2;
ein wenig löschen:
char &= ~BIT_3
ein bisschen Umschalten
char ^= BIT_4
Diese Hilfe?
Es gibt einen Standardbibliothekscontainer für Bits: std :: vector. Es ist in der Fachbibliothek Raum effizient zu sein. Es gibt auch einen Schub dynamic_bitset Klasse.
Diese lassen Sie Operationen auf einem Satz von Booleschen Werten, mit einem Bit pro Wert des zugrunde liegenden Speichers durchführen.
Erhöhung dynamische bitset Dokumentation
Für die STL-Dokumentation finden Sie Ihre Compiler-Dokumentation.
Natürlich können Sie auch die einzelnen Bits in anderen ganzzahligen Typen von Hand adressieren. Wenn Sie das tun, sollten Sie unsigned-Typen verwenden, so dass Sie keine undefinierten Verhalten, wenn sich entscheiden, eine Verschiebung nach rechts auf einen Wert mit dem hohen Bit gesetzt zu tun. Aber es klingt wie Sie die Behälter wollen.
Zu dem Kommentator, der behauptete, dies dauert 32x mehr Platz als nötig: boost :: dynamic_bitset und Vektor sind darauf spezialisiert, pro Eintrag ein Bit zu verwenden, und so gibt es keinen Raum Strafe, unter der Annahme, dass Sie tatsächlich mehr als die Anzahl der Bits in einem primitiven Typ. Diese Klassen können Sie einzelne Bits in einem großen Behälter mit effizienten zugrunde liegenden Speicher adressieren. Wenn Sie gerade (sagen wir) 32 Bits wollen, mit allen Mitteln, verwenden Sie einen int. Wenn Sie einige große Anzahl von Bits möchten, können Sie einen Bibliothekscontainer verwenden.