Поскольку никто не затронул тему, почему они полезны:
Я много использую побитовые операции при работе с флагами. Например, если вы хотите передать ряд флагов операции (скажем, File.Open()
с включенными режимами чтения и записи), вы можете передать их как одно значение. Это достигается путем присвоения каждому возможному флагу собственного бита в битовом наборе (byte, short, int или long). Например:
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 текущего значения с помощью (LEFT | RIGHT), который в этом случае отключает LEFT и RIGHT.
Битовый сдвиг полезен в нескольких случаях.
x << y
такой же как
х * 2 у
если вам нужно быстро умножить на степень двойки, но следите за тем, чтобы 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)