Поскольку никто не затронул тему, почему они полезны:
Я часто использую побитовые операции при работе с флагами. Например, если вы хотите передать серию флагов операции (скажем, File.Open()
, когда включены режим чтения и режим записи), вы можете передать их как одно значение. Это достигается назначением каждому возможному флагу своего собственного бита в наборе битов (байтов, коротких, целых или длинных). Например:
Read: 00000001
Write: 00000010
Таким образом, если вы хотите передать чтение и запись, вы должны передать (READ | WRITE), который затем объединит их в
00000011
Который затем может быть расшифрован на другом конце, как:
if ((flag & Read) != 0) { //...
который проверяет
00000011 &
00000001
, который возвращает
00000001
, который не равен 0, поэтому флаг указывает READ.
Вы можете использовать XOR для переключения различных битов. Я использовал это при использовании флага для указания направленных входов (вверх, вниз, влево, вправо). Например, если спрайт движется горизонтально, и я хочу, чтобы он вращался:
Up: 00000001
Down: 00000010
Left: 00000100
Right: 00001000
Current: 00000100
Я просто XOR текущее значение с помощью (ВЛЕВО | ВПРАВО), который в этом случае выключит ВЛЕВО и ВПРАВО.
Сдвиг битов полезен в нескольких случаях.
x << y
совпадает с
x * 2 y
если вам нужно быстро умножить на степень два, но не упустить 1 бит в верхнем бите - это делает число отрицательным, если оно не подписано. Это также полезно при работе с данными разных размеров. Например, чтение целого числа из четырех байтов:
int val = (A << 24) | (B << 16) | (C << 8) | D;
Предполагая, что A является старшим байтом, а D - младшим. Это закончилось бы как:
A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011
Цвета часто сохраняются таким образом (самый старший байт либо игнорируется, либо используется как альфа):
A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000
Чтобы снова найти значения, просто сдвиньте биты вправо, пока они не окажутся внизу, а затем замаскируйте оставшиеся биты высшего порядка:
Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF
0xFF
совпадает с 11111111
. По сути, для Red вы должны сделать следующее:
Color >> 16 = (filled in 00000000 00000000)11111111 00010101 (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)