Ich versuche, eine Datenkomprimierungsidee zu implementieren, die ich hatte, und da ich mir vorstelle, sie gegen einen großen Korpus von Testdaten laufen zu lassen, hatte ich gedacht, sie in C zu programmieren (ich habe meistens Erfahrung in Skriptsprachen) wie Ruby und Tcl.)
Wenn ich in den O'Reilly-Büchern über C nachdenke, merke ich, dass ich die Bits einer einfachen Variable vom Typ "char" oder "int" nicht einfach indizieren kann, wie ich das gerne bitweise vergleichen würde Betreiber.
Bin ich in dieser Wahrnehmung richtig? Ist es vernünftig für mich, einen Aufzählungstyp für die Darstellung eines Bits zu verwenden (und ein Array von diesen zu erstellen und Funktionen zum Konvertieren in und aus char zu schreiben)? Wenn ja, ist ein solcher Typ und Funktionen bereits irgendwo in einer Standardbibliothek definiert? Gibt es andere (bessere?) Ansätze? Gibt es irgendwo einen Code, auf den mich jemand verweisen könnte?
Danke -
Nach dem, was Kyle gesagt hat, kannst du mit einem Makro die harte Arbeit für dich erledigen.
Es ist möglich.
Um das n-te Bit zu setzen, verwenden Sie ODER:
x | = (1 & lt; & lt; 5); // setzt den 6.-von richtig
Um ein bisschen zu löschen, verwenden Sie UND:
x & amp; = (1 & lt; & lt; 5); // löscht 6. von rechts
Um ein bisschen umzudrehen, benutze XOR:
x ^ = (1 & lt; & lt; 5); // dreht 6.-von-rechts
Oder ...
%Vor%Dann können Sie es in Code wie verwenden:
%Vor%Es ist möglich.
Um das n-te Bit zu setzen, verwenden Sie ODER:
%Vor%Um ein bisschen zu löschen, verwenden Sie UND:
%Vor%Um ein bisschen umzudrehen, benutze XOR:
%Vor%Um den Wert eines Bits zu erhalten, verwenden Sie shift und AND:
%Vor%Hinweis: Das Shift-Recht 5 ist, um sicherzustellen, dass der Wert entweder 0 oder 1 ist. Wenn Sie nur an 0 interessiert sind / nicht 0, können Sie ohne die Verschiebung auskommen.
Theorie
Es gibt keine C-Syntax für den Zugriff auf das n-te Bit eines eingebauten Datentyps (z. B. ein 'char'). Sie können jedoch mit einer logischen UND-Operation auf Bits zugreifen und Bits mit einer logischen ODER-Operation setzen.
Als Beispiel, sagen Sie, dass Sie eine Variable haben, die 1101 enthält und Sie das zweite Bit von links überprüfen möchten. Führen Sie einfach ein logisches UND mit 0100 aus:
%Vor%Wenn das Ergebnis nicht Null ist, muss das 2. Bit gesetzt worden sein; Sonst wurde nicht eingestellt.
Wenn Sie das 3. Bit von links setzen wollen, führen Sie ein logisches ODER mit 0010 durch:
%Vor%Sie können die C-Operatoren & amp; & amp; (für UND) 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 besteht darin, sich daran zu erinnern, dass das niedrigstwertige Bit (LSB) 1s zählt, das nächste LSB 2s zählt, dann 4s usw. Somit ist das Bitzugriffsmuster für das n-te LSB (beginnend bei 0) einfach der Wert von 2 ^ n. Der einfachste Weg, dies in C zu berechnen, ist, den Binärwert 0001 (in diesem Beispiel mit vier Bits) um die erforderliche Anzahl von Stellen nach links zu verschieben. Da dieser Wert in vorzeichenlosen, ganzzahligen Mengen immer gleich 1 ist, ist dies nur '1 & lt; & lt; n '
Beispiel
%Vor%Dieses Beispiel wurde nicht getestet, sollte aber zur Veranschaulichung der allgemeinen Idee dienen.
Um den Zustand des Bits mit dem spezifischen Index abzufragen:
%Vor%Um das Bit zu setzen:
%Vor%Um das Bit neu zu starten:
%Vor%Einzelne Bits können wie folgt indiziert werden.
Definieren Sie eine Struktur wie diese:
%Vor%Wenn ich nun die einzelnen Bitwerte einer Variablen namens "value" kennenlernen möchte, gehen Sie folgendermaßen vor:
%Vor%Um zu sehen, ob Bit 2 hoch oder niedrig ist:
%Vor%Hoffe, das hilft.
Nach dem, was Kyle gesagt hat, kannst du mit einem Makro die harte Arbeit für dich erledigen.
Es ist möglich.
Um das n-te Bit zu setzen, verwenden Sie ODER:
x | = (1 & lt; & lt; 5); // setzt den 6.-von richtig
Um ein bisschen zu löschen, verwenden Sie UND:
x & amp; = (1 & lt; & lt; 5); // löscht 6. von rechts
Um ein bisschen umzudrehen, benutze XOR:
x ^ = (1 & lt; & lt; 5); // dreht 6.-von-rechts
Oder ...
%Vor%Dann können Sie es in Code wie verwenden:
%Vor%Sehen Sie sich die Antworten zu diese Frage .
Es ist möglich.
Um das n-te Bit zu setzen, verwenden Sie ODER:
%Vor%Um ein bisschen zu löschen, verwenden Sie UND:
%Vor%Um ein bisschen umzudrehen, benutze XOR:
%Vor%Um den Wert eines Bits zu erhalten, verwenden Sie shift und AND:
%Vor%Hinweis: Das Shift-Recht 5 ist, um sicherzustellen, dass der Wert entweder 0 oder 1 ist. Wenn Sie nur an 0 interessiert sind / nicht 0, können Sie ohne die Verschiebung auskommen.
Ich versuche, eine Datenkomprimierungsidee zu implementieren, die ich hatte, und da ich mir vorstelle, sie gegen einen großen Korpus von Testdaten laufen zu lassen, hatte ich gedacht, sie in C zu programmieren (ich habe meistens Erfahrung in Skriptsprachen) wie Ruby und Tcl.)
Wenn ich in den O'Reilly-Büchern über C nachdenke, merke ich, dass ich die Bits einer einfachen Variable vom Typ "char" oder "int" nicht einfach indizieren kann, wie ich das gerne bitweise vergleichen würde Betreiber.
Bin ich in dieser Wahrnehmung richtig? Ist es vernünftig für mich, einen Aufzählungstyp für die Darstellung eines Bits zu verwenden (und ein Array von diesen zu erstellen und Funktionen zum Konvertieren in und aus char zu schreiben)? Wenn ja, ist ein solcher Typ und Funktionen bereits irgendwo in einer Standardbibliothek definiert? Gibt es andere (bessere?) Ansätze? Gibt es irgendwo einen Code, auf den mich jemand verweisen könnte?
Danke -
Einzelne Bits können wie folgt indiziert werden.
Definieren Sie eine Struktur wie diese:
%Vor%Wenn ich nun die einzelnen Bitwerte einer Variablen namens "value" kennenlernen möchte, gehen Sie folgendermaßen vor:
%Vor%Um zu sehen, ob Bit 2 hoch oder niedrig ist:
%Vor%Hoffe, das hilft.
Theorie
Es gibt keine C-Syntax für den Zugriff auf das n-te Bit eines eingebauten Datentyps (z. B. ein 'char'). Sie können jedoch mit einer logischen UND-Operation auf Bits zugreifen und Bits mit einer logischen ODER-Operation setzen.
Als Beispiel, sagen Sie, dass Sie eine Variable haben, die 1101 enthält und Sie das zweite Bit von links überprüfen möchten. Führen Sie einfach ein logisches UND mit 0100 aus:
%Vor%Wenn das Ergebnis nicht Null ist, muss das 2. Bit gesetzt worden sein; Sonst wurde nicht eingestellt.
Wenn Sie das 3. Bit von links setzen wollen, führen Sie ein logisches ODER mit 0010 durch:
%Vor%Sie können die C-Operatoren & amp; & amp; (für UND) 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 besteht darin, sich daran zu erinnern, dass das niedrigstwertige Bit (LSB) 1s zählt, das nächste LSB 2s zählt, dann 4s usw. Somit ist das Bitzugriffsmuster für das n-te LSB (beginnend bei 0) einfach der Wert von 2 ^ n. Der einfachste Weg, dies in C zu berechnen, ist, den Binärwert 0001 (in diesem Beispiel mit vier Bits) um die erforderliche Anzahl von Stellen nach links zu verschieben. Da dieser Wert in vorzeichenlosen, ganzzahligen Mengen immer gleich 1 ist, ist dies nur '1 & lt; & lt; n '
Beispiel
%Vor%Dieses Beispiel wurde nicht getestet, sollte aber zur Veranschaulichung der allgemeinen Idee dienen.
Um den Zustand des Bits mit dem spezifischen Index abzufragen:
%Vor%Um das Bit zu setzen:
%Vor%Um das Bit neu zu starten:
%Vor%Versuchen Sie es mit Bitfeldern. Seien Sie vorsichtig, die Implementierung kann je nach Compiler variieren.
Wenn Sie ein wenig indizieren möchten, könnten Sie:
%Vor%ruft die MSB eines Zeichens ab. Du könntest sogar die richtige Schicht weglassen und einen Test auf 0 machen.
%Vor%Wenn das Bit gesetzt ist, wird das Ergebnis & gt; 0;
Offensichtlich müssen Sie die Maske ändern, um verschiedene Bits zu erhalten (NB: 0xF ist die Bitmaske, wenn sie unklar ist). Es ist möglich, zahlreiche Masken zu definieren, z. B.
%Vor%usw. ...
Dies gibt Ihnen:
%Vor%Sie können diese Definitionen im obigen Code verwenden, um ein Bit innerhalb eines Makros oder einer Funktion erfolgreich zu indizieren.
Um ein bisschen zu setzen:
%Vor%Um ein bisschen zu klären:
%Vor%Um ein Bit umzuschalten
%Vor%Diese Hilfe?
Es gibt einen Standardbibliothekscontainer für Bits: std :: vector. Es ist darauf spezialisiert, dass die Bibliothek platzsparend ist. Es gibt auch eine Boost-Klasse dynamic_bitset.
Damit können Sie Operationen für eine Reihe von booleschen Werten ausführen, wobei ein Bit pro Wert des zugrunde liegenden Speichers verwendet wird.
Dynamische Bitset-Dokumentation aktualisieren
Die STL-Dokumentation finden Sie in der Compiler-Dokumentation.
Natürlich können Sie die einzelnen Bits auch in anderen ganzzahligen Typen von Hand adressieren. Wenn Sie dies tun, sollten Sie unsignierte Typen verwenden, damit Sie kein undefiniertes Verhalten erhalten, wenn Sie eine Verschiebung nach rechts auf einen Wert mit gesetztem High-Bit treffen. Es klingt jedoch so, als ob Sie die Container wollen.
Für den Kommentator, der behauptet, dass dies 32x mehr Speicherplatz als nötig benötigt: boost :: dynamic_bitset und vector sind darauf spezialisiert, ein Bit pro Eintrag zu verwenden, und daher gibt es keine Platzstrafe, vorausgesetzt, Sie wollen tatsächlich mehr als die Anzahl Bits in einem primitiven Typ. Mit diesen Klassen können Sie einzelne Bits in einem großen Container mit effizientem zugrunde liegenden Speicher adressieren. Wenn Sie (sagen wir) nur 32 Bits wollen, benutzen Sie unbedingt einen int. Wenn Sie eine große Anzahl von Bits benötigen, können Sie einen Bibliothekscontainer verwenden.
Es gibt einen Standardbibliothekscontainer für Bits: std :: vector. Es ist darauf spezialisiert, dass die Bibliothek platzsparend ist. Es gibt auch eine Boost-Klasse dynamic_bitset.
Damit können Sie Operationen für eine Reihe von booleschen Werten ausführen, wobei ein Bit pro Wert des zugrunde liegenden Speichers verwendet wird.
Dynamische Bitset-Dokumentation aktualisieren
Die STL-Dokumentation finden Sie in der Compiler-Dokumentation.
Natürlich können Sie die einzelnen Bits auch in anderen ganzzahligen Typen von Hand adressieren. Wenn Sie dies tun, sollten Sie unsignierte Typen verwenden, damit Sie kein undefiniertes Verhalten erhalten, wenn Sie eine Verschiebung nach rechts auf einen Wert mit gesetztem High-Bit treffen. Es klingt jedoch so, als ob Sie die Container wollen.
Für den Kommentator, der behauptet, dass dies 32x mehr Speicherplatz als nötig benötigt: boost :: dynamic_bitset und vector sind darauf spezialisiert, ein Bit pro Eintrag zu verwenden, und daher gibt es keine Platzstrafe, vorausgesetzt, Sie wollen tatsächlich mehr als die Anzahl Bits in einem primitiven Typ. Mit diesen Klassen können Sie einzelne Bits in einem großen Container mit effizientem zugrunde liegenden Speicher adressieren. Wenn Sie (sagen wir) nur 32 Bits wollen, benutzen Sie unbedingt einen int. Wenn Sie eine große Anzahl von Bits benötigen, können Sie einen Bibliothekscontainer verwenden.
Tags und Links c coding-style bit-manipulation