Wie kann man ein Bit setzen, löschen und umschalten?
Verwenden Sie den bitweisen OR-Operator (|
), um ein Bit zu setzen.
number |= 1UL << n;
Das setzt das n
te Bit von number
. n
sollte Null sein, wenn Sie das 1
ste Bit setzen wollen und so weiter bis n-1
, wenn Sie das n
te Bit setzen wollen.
Benutzen Sie 1ULL
, wenn number
breiter als unsigned long
ist; die Beförderung von 1UL << n
geschieht erst nach der Auswertung von 1UL << n
, wo es undefiniertes Verhalten ist, um mehr als die Breite eines long
zu verschieben. Das Gleiche gilt für alle anderen Beispiele.
Verwenden Sie den bitweisen AND-Operator (&
), um ein Bit zu löschen.
number &= ~(1UL << n);
Damit wird das n
te Bit von number
gelöscht. Sie müssen die Bitfolge mit dem bitweisen NOT-Operator (~
) invertieren und dann UND-verknüpfen.
Der XOR-Operator (^
) kann verwendet werden, um ein Bit umzuschalten.
number ^= 1UL << n;
Damit wird das n
te Bit von Zahl
umgeschaltet.
Du hast nicht danach gefragt, aber ich könnte es genauso gut hinzufügen.
Um ein Bit zu prüfen, verschiebt man die Zahl n nach rechts und verknüpft sie dann bitweise mit AND:
bit = (number >> n) & 1U;
Das setzt den Wert des n
ten Bits von number
in die Variable bit
.
Das Setzen des n
-ten Bits auf entweder 1
oder 0
kann in einer 2er-Komplement-C++-Implementierung wie folgt erreicht werden:
number ^= (-x ^ number) & (1UL << n);
Das Bit n
wird gesetzt, wenn x
1
ist, und gelöscht, wenn x
0
ist. Wenn x
einen anderen Wert hat, erhält man Müll. x = !!x
setzt es boolesch auf 0 oder 1.
Um dies unabhängig vom Verhalten der 2er-Komplement-Negation zu machen (wo bei -1
alle Bits gesetzt sind, im Gegensatz zu einer 1er-Komplement- oder Vorzeichen/Magnitude-C++-Implementierung), verwenden Sie die Negation ohne Vorzeichen.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
oder
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 Bitmanipulationen zu verwenden.
oder
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
löscht das n
te Bit und (x << n)
setzt das n
te Bit auf x
.
Es ist auch generell eine gute Idee, Code nicht zu kopieren/einzufügen, und so verwenden viele Leute Präprozessormakros (wie die Community-Wiki-Antwort weiter unten) oder eine Art von Kapselung.
Manchmal lohnt es sich, ein "enum" zu verwenden, um die Bits zu benennen:
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
Verwenden Sie dann später die Namen. D.h. schreibe
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
zum Setzen, Löschen und Testen. Auf diese Weise verbergen Sie die magischen Zahlen vor dem Rest Ihres Codes.
Ansonsten schließe ich mich der Lösung von Jeremy an.
Verwenden Sie die bitweisen Operatoren: &
|
Um das letzte Bit in 000b
zu setzen:
foo = foo | 001b
Um das letzte Bit in foo
zu prüfen:
if ( foo & 001b ) ....
Um das letzte Bit in "foo" zu löschen:
foo = foo & 110b
Der Klarheit halber habe ich XXXb
verwendet. Je nach der Datenstruktur, in die Sie die Bits packen, werden Sie wahrscheinlich mit der HEX-Darstellung arbeiten.