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 -

War es hilfreich?

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

Haben Sie einen Blick auf die Antworten auf

Theorie

Es gibt keine C-Syntax für den Zugriff auf oder die Einstellung den n-te Bit eines integrierten Datentypen (beispielsweise ein ‚char‘). Sie können jedoch Bits Zugriff auf einen logischen UND-Verknüpfung mit und stellten Bits eine logische ODER-Verknüpfung verwendet wird.

Als Beispiel sagen, dass Sie eine Variable, die 1101 hält und Sie wollen das zweite Bit von links zu überprüfen. ein logisches UND mit 0100 einfach ausführen:

1101
0100
---- AND
0100

Wenn das Ergebnis nicht Null ist, dann ist das zweite Bit gesetzt worden sein; ansonsten wurde nicht gesetzt ist.

Wenn Sie das dritte Bit von links gesetzt werden soll, führen Sie dann ein logisches ODER mit 0010:

1101
0010
---- OR
1111

Sie können die C Operatoren && (für AND) und || (Für OR), um diese Aufgaben auszuführen. Sie müssen die Bit-Zugriffsmuster (die 0100 und 0010 in den obigen Beispielen) selbst konstruieren. Der Trick ist, sich daran zu erinnern, dass das niedrigstwertige Bit (LSB) zählt 1s, die nächsten LSB zählt 2s, dann 4s usw. das Bit Zugriffsmuster für die n-te LSB (ab 0) ist also einfach der Wert von 2 ^ n. Der einfachste Weg, um dies in C zu berechnen, ist es, den Binärwert 0001 (in diesem Beispiel vier Bit) nach links um die erforderlichen Anzahl von Stellen zu verschieben. Da dieser Wert immer gleich 1 in unsigned integer artigen Mengen, das ist nur ‚1 << n‘

Beispiel:

unsigned char myVal = 0x65; /* in hex; this is 01100101 in binary. */

/* Q: is the 3-rd least significant bit set (again, the LSB is the 0th bit)? */
unsigned char pattern = 1;
pattern <<= 3; /* Shift pattern left by three places.*/

if(myVal && (char)(1<<3)) {printf("Yes!\n");} /* Perform the test. */

/* Set the most significant bit. */
myVal |= (char)(1<<7);

hat dieses Beispiel nicht getestet, sondern soll dazu dienen, die allgemeine Idee zu illustrieren.

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.

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top