Πώς ρυθμίζετε, καθαρίζετε και αλλάζετε ένα bit;
Χρησιμοποιήστε τον τελεστή bitwise OR (|
) για να ορίσετε ένα bit.
number |= 1UL << n;
Αυτό θα θέσει το n
οστό bit του αριθμού
. Το n
θα πρέπει να είναι μηδέν, αν θέλετε να θέσετε το 1
οστό bit και ούτω καθεξής μέχρι το n-1
, αν θέλετε να θέσετε το n
οστό bit.
Χρησιμοποιήστε το 1ULL
αν ο αριθμός
είναι ευρύτερος από το unsigned long
- η προώθηση του 1UL << n
δεν συμβαίνει μέχρι να αξιολογηθεί το 1UL << n
όπου είναι απροσδιόριστη συμπεριφορά η μετατόπιση κατά περισσότερο από το πλάτος ενός long
. Το ίδιο ισχύει και για όλα τα υπόλοιπα παραδείγματα.
Χρησιμοποιήστε τον τελεστή bitwise AND (&
) για να καθαρίσετε ένα bit.
number &= ~(1UL << n);
Αυτό θα καθαρίσει το n
οστό bit του αριθμού
. Πρέπει να αντιστρέψετε τη συμβολοσειρά bit με τον τελεστή bitwise NOT (~
), και στη συνέχεια να την AND.
Ο τελεστής XOR (^
) μπορεί να χρησιμοποιηθεί για την εναλλαγή ενός bit.
number ^= 1UL << n;
Αυτό θα αλλάξει το n
-οστό bit του αριθμού
.
Δεν το ζητήσατε αυτό, αλλά θα μπορούσα να το προσθέσω.
Για να ελέγξετε ένα bit, μετατοπίστε τον αριθμό n προς τα δεξιά και στη συνέχεια κάντε bitwise AND:
bit = (number >> n) & 1U;
Αυτό θα βάλει την τιμή του n
-οστού bit του αριθμού
στη μεταβλητή bit
.
Η ρύθμιση του n
-οστού bit σε 1
ή 0
μπορεί να επιτευχθεί με τα ακόλουθα σε μια υλοποίηση της C++ με συμπλήρωμα 2:
number ^= (-x ^ number) & (1UL << n);
Το bit n
θα τεθεί αν το x
είναι 1
, και θα καθαριστεί αν το x
είναι 0
. Αν το x
έχει κάποια άλλη τιμή, θα έχετε σκουπίδια. Το x = !!x
θα το μετατρέψει σε 0 ή 1.
Για να το κάνετε αυτό ανεξάρτητο από τη συμπεριφορά της άρνησης του συμπληρώματος 2 (όπου το -1
έχει όλα τα bits ρυθμισμένα, σε αντίθεση με την υλοποίηση του συμπληρώματος 1 ή του πρόσημου/μεγέθους της C++), χρησιμοποιήστε την άρνηση χωρίς πρόσημο.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
ή
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
Είναι γενικά καλή ιδέα να χρησιμοποιείτε τύπους χωρίς πρόσημο για φορητό χειρισμό bit.
ή
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
θα καθαρίσει το n
οστό bit και (x << n)
θα θέσει το n
οστό bit στο x
.
Είναι επίσης γενικά μια καλή ιδέα να μην αντιγράφουμε/επικολλάμε κώδικα γενικά και έτσι πολλοί άνθρωποι χρησιμοποιούν μακροεντολές προεπεξεργαστή (όπως η απάντηση του community wiki πιο κάτω) ή κάποιο είδος ενθυλάκωσης.
Μερικές φορές αξίζει να χρησιμοποιήσετε ένα enum
για να ονομάσετε τα bits:
enum ThingFlags = {
ThingMask = 0x0000,
ThingFlag0 = 1 << 0,
ThingFlag1 = 1 << 1,
ThingError = 1 << 8,
}
Στη συνέχεια, χρησιμοποιήστε τα ονόματα αργότερα. Δηλαδή, γράψτε
thingstate |= ThingFlag1;
thingstate &= ~ThingFlag0;
if (thing & ThingError) {...}
για να ορίσετε, να καθαρίσετε και να ελέγξετε. Με αυτόν τον τρόπο κρύβετε τους μαγικούς αριθμούς από τον υπόλοιπο κώδικα.
Κατά τα άλλα υποστηρίζω τη λύση του Jeremy.
Χρησιμοποιήστε τους τελεστές bitwise: &
|
Για να θέσετε το τελευταίο bit στο 000b
:
foo = foo | 001b
Για να ελέγξετε το τελευταίο bit στο foo
:
if ( foo & 001b ) ....
Για να καθαρίσετε το τελευταίο bit στο foo
:
foo = foo & 110b
Χρησιμοποίησα το XXXb
για λόγους σαφήνειας. Πιθανόν να εργάζεστε με αναπαράσταση HEX, ανάλογα με τη δομή δεδομένων στην οποία πακετάρετε τα bits.