Ответ 1
Вы можете установить четвертый бит числа с помощью OR-ing со значением, равным нулю всюду, кроме четвертого. Это можно сделать как
x |= (1u << 3);
Аналогичным образом, вы можете очистить четвертый бит, используя AND, со значением, которое является везде, кроме четвертого. Например:
x &= ~(1u << 3);
Наконец, вы можете переключить четвертый бит с помощью XOR-ing со значением, равным нулю всюду, кроме четвертого бита:
x ^= (1u << 3);
Чтобы понять, почему это работает, нам нужно посмотреть на две вещи:
- Каково поведение оператора
<<
в этом контексте? - Каково поведение операторов AND, OR и XOR здесь?
Во всех трех приведенных выше фрагментах кода мы использовали оператор <<
для генерации значения. Оператор <<
является побитовым сдвигом-левым оператором, который принимает значение, а затем сдвигает все его биты на несколько шагов влево. В вашем случае я использовал
1u << 3
принять значение 1 (которое имеет двоичное представление 1) и затем сдвинуть все его биты на три точки, заполнив недостающие значения с помощью 0. Это создает двоичное значение 1000
, которое имеет бит, установленный в четвертый бит.
Теперь, почему
x |= (1u << 3);
установить четвертый бит числа? Это связано с тем, как работает оператор OR. Оператор |=
похож на +=
или *=
, за исключением побитового ИЛИ, что эквивалентно
x = x | (1u << 3);
Итак, почему OR-ing x с двоичным значением 1000
устанавливает свой четвертый бит? Это связано с тем, как определяется OR:
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1
Что еще более важно, мы можем переписать это более компактно, так как
x | 0 == x
x | 1 == 1
Это чрезвычайно важный факт, потому что это означает, что OR-ing любой бит с нолем не изменяет значение бита, тогда как OR-ing любой бит с 1 всегда устанавливает бит в один. Это означает, что когда мы пишем
x |= (1u << 3);
поскольку (1u < 3) представляет собой значение, равное нулю всюду, кроме четвертого бита, побитовое ИЛИ оставляет все биты x неизмененными, за исключением четвертого бита, который затем устанавливается равным единице. В более общем случае, OR-число с значением, которое представляет собой серию нулей и единиц, сохранит все значения, в которых бит равен нулю, и установите все значения, в которых бит равен единице.
Теперь посмотрим
x &= ~(1u << 3);
Здесь используется оператор побитового дополнения ~
, который принимает число и переворачивает все его биты. Если мы предположим, что целые числа представляют собой два байта (просто для простоты), это означает, что фактическое кодирование (1u << 3)
равно
0000000000001000
Когда мы возьмем дополнение к этому, получим число
1111111111110111
Теперь посмотрим, что произойдет, когда мы побитовое и два значения вместе. Оператор И имеет эту интересную таблицу истинности:
0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1
Или, более компактно:
x & 0 == 0
x & 1 == x
Обратите внимание, что это означает, что если мы и два числа вместе, результирующее значение будет таким, чтобы все биты AND-ed с нулем были установлены на ноль, а все остальные биты сохранялись. Это означает, что если мы И с
~(1u << 3)
мы имеем AND с
1111111111110111
Таким образом, в соответствии с нашей таблицей, это означает "сохранить все биты, кроме четвертого бита, как есть, а затем изменить четвертый бит на нуль".
В более общем плане, если вы хотите очистить набор битов, создайте число, которое есть везде, где вы хотите сохранить биты без изменений, и ноль, где вы хотите очистить бит.
Наконец, давайте посмотрим, почему
x ^= (1u << 3)
Отбрасывает четвертый бит числа. Это связано с тем, что бинарный оператор XOR имеет эту таблицу истинности:
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0
Обратите внимание, что
x ^ 0 == 0
x ^ 1 == ~x
Где ~x
противоположно x; это 0 для 1 и 1 для 0. Это означает, что если мы XOR x со значением (1u << 3)
, мы XOR-ing с
0000000000001000
Таким образом, это означает "сохранить все биты, но четвертый бит установлен как есть, но переверните четвертый бит". В более общем плане, если вы хотите перевернуть некоторое количество бит, XOR - это значение с числом, которое имеет нулевое значение, где вы хотите сохранить биты целыми, и тот, где вы хотите перевернуть эти биты.
Надеюсь, это поможет!