3116 Stimmen

Wie kann man ein einzelnes Bit setzen, löschen und umschalten?

Wie kann man ein Bit setzen, löschen und umschalten?

90 Stimmen

Lesen Sie dies: graphics.stanford.edu/~seander/bithacks.html und, wenn du das gemeistert hast, lies das hier: realtimecollisiondetection.net/blog/?p=78

22 Stimmen

Das könnte Sie auch interessieren Der Gebissverdreher , Bit Twiddling Hacks und Die Aggregat-Magie-Algorithmen .

0 Stimmen

Das wirft die Frage auf, was die kanonische Frage für mehrere Bits ist.

4318voto

Paige Ruten Punkte 164391

Einstellung eines Bits

Verwenden Sie den bitweisen OR-Operator ( | ), um ein Bit zu setzen.

number |= 1UL << n;

Damit wird die n ein bisschen number . n sollte Null sein, wenn Sie die 1 Bit und so weiter bis zu n-1 wenn Sie die Option n Das Stück.

Utilice 1ULL wenn number ist breiter als unsigned long Förderung von 1UL << n erfolgt erst nach der Auswertung der 1UL << n wo es ein undefiniertes Verhalten ist, sich um mehr als die Breite einer long . Das Gleiche gilt für alle anderen Beispiele.

Ein wenig aufräumen

Verwenden Sie den bitweisen AND-Operator ( & ), um ein wenig zu löschen.

number &= ~(1UL << n);

Dadurch wird die n ein bisschen number . Sie müssen die Bitfolge mit dem bitweisen NOT-Operator invertieren ( ~ ), dann UND.

Ein bisschen hin und her schalten

Der XOR-Operator ( ^ ) kann verwendet werden, um ein Bit umzuschalten.

number ^= 1UL << n;

Das schaltet die n ein bisschen number .

Ein bisschen nachsehen

Sie haben zwar nicht danach gefragt, aber ich kann es trotzdem hinzufügen.

Um ein Bit zu prüfen, verschiebt man die Zahl n nach rechts und setzt sie dann bitweise UND:

bit = (number >> n) & 1U;

Dadurch wird der Wert der n ein bisschen number in die Variable bit .

Ändern der n th Bit zu x

Einstellung der n Bit entweder auf 1 ou 0 kann bei einer 2er-Komplement-C++-Implementierung wie folgt erreicht werden:

number ^= (-x ^ number) & (1UL << n);

Bit n wird gesetzt, wenn x es 1 und gelöscht, wenn x es 0 . Wenn x einen anderen Wert hat, erhält man Müll. x = !!x wird boolesch auf 0 oder 1 gesetzt.

Um dies unabhängig vom Verhalten bei der Negation des 2er-Komplements zu machen (wobei -1 alle Bits gesetzt hat, anders als bei einer 1er-Komplement- oder Vorzeichen/Magnitude-C++-Implementierung), verwenden Sie die Negation ohne Vorzeichen.

number ^= (-(unsigned long)x ^ number) & (1UL << n);

o

unsigned long newbit = !!x;    // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);

Es ist im Allgemeinen eine gute Idee, vorzeichenlose Typen für portable Bitmanipulation zu verwenden.

o

number = (number & ~(1UL << n)) | (x << n);

(number & ~(1UL << n)) wird die n th Bit und (x << n) setzt die n th Bit zu x .

Es ist auch generell eine gute Idee, Code nicht zu kopieren/einzufügen, und so verwenden viele Leute Präprozessormakros (wie die Antwort des Community-Wikis weiter unten ) oder eine Art von Verkapselung.

555voto

Martin York Punkte 245363

Verwendung der Standard-C++-Bibliothek: std::bitset<N> .

Oder die Boost Version: boost::dynamic_bitset .

Es ist nicht nötig, selbst zu rollen:

#include <bitset>
#include <iostream>

int main()
{
    std::bitset<5> x;

    x[1] = 1;
    x[2] = 0;
    // Note x[0-4]  valid

    std::cout << x << std::endl;
}

[Alpha:] > ./a.out
00010

Die Boost-Version erlaubt ein Bitset in Laufzeitgröße im Vergleich zu einer Standardbibliothek Bitset in Kompilierzeitgröße.

284voto

Ferruccio Punkte 96076

Die andere Möglichkeit ist die Verwendung von Bitfeldern:

struct bits {
    unsigned int a:1;
    unsigned int b:1;
    unsigned int c:1;
};

struct bits mybits;

definiert ein 3-Bit-Feld (eigentlich sind es drei 1-Bit-Felder). Bit-Operationen werden nun etwas (haha) einfacher:

Zum Setzen oder Löschen eines Bits:

mybits.b = 1;
mybits.c = 0;

Um ein bisschen zu schalten:

mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1;  /* all work */

Ich prüfe ein wenig:

if (mybits.c)  //if mybits.c is non zero the next line below will execute

Dies funktioniert nur bei Bitfeldern mit fester Größe. Andernfalls müssen Sie auf die in früheren Beiträgen beschriebenen Techniken zur Bitverschiebung zurückgreifen.

249voto

Steve Karg Punkte 11

Ich verwende Makros, die in einer Header-Datei definiert sind, um die Bits zu setzen und zu löschen:

/* a=target variable, b=bit number to act upon 0-n */
#define BIT_SET(a,b) ((a) |= (1ULL<<(b)))
#define BIT_CLEAR(a,b) ((a) &= ~(1ULL<<(b)))
#define BIT_FLIP(a,b) ((a) ^= (1ULL<<(b)))
#define BIT_CHECK(a,b) (!!((a) & (1ULL<<(b))))        // '!!' to make sure this returns 0 or 1

#define BITMASK_SET(x, mask) ((x) |= (mask))
#define BITMASK_CLEAR(x, mask) ((x) &= (~(mask)))
#define BITMASK_FLIP(x, mask) ((x) ^= (mask))
#define BITMASK_CHECK_ALL(x, mask) (!(~(x) & (mask)))
#define BITMASK_CHECK_ANY(x, mask) ((x) & (mask))

142voto

Manchmal lohnt es sich, einen enum a 名前 die Bits:

enum ThingFlags = {
  ThingMask  = 0x0000,
  ThingFlag0 = 1 << 0,
  ThingFlag1 = 1 << 1,
  ThingError = 1 << 8,
}

Verwenden Sie dann die Namen später. D.h. schreiben

thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}

zum Einstellen, Löschen und Prüfen. Auf diese Weise verbergen Sie die magischen Zahlen vor dem Rest Ihres Codes.

Abgesehen davon unterstütze ich Die Lösung von Paige Ruten .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X