Мы имеем целое число
int x = 50;
в двоичном формате, это
00110010
Как я могу изменить четвертый (4-й) бит программно?
Мы имеем целое число
int x = 50;
в двоичном формате, это
00110010
Как я могу изменить четвертый (4-й) бит программно?
Вы можете установить четвертый бит числа с помощью OR-ing со значением, равным нулю всюду, кроме четвертого. Это можно сделать как
x |= (1u << 3);
Аналогичным образом, вы можете очистить четвертый бит, используя AND, со значением, которое является везде, кроме четвертого. Например:
x &= ~(1u << 3);
Наконец, вы можете переключить четвертый бит с помощью XOR-ing со значением, равным нулю всюду, кроме четвертого бита:
x ^= (1u << 3);
Чтобы понять, почему это работает, нам нужно посмотреть на две вещи:
<<
в этом контексте?Во всех трех приведенных выше фрагментах кода мы использовали оператор <<
для генерации значения. Оператор <<
является побитовым сдвигом-левым оператором, который принимает значение, а затем сдвигает все его биты на несколько шагов влево. В вашем случае я использовал
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 - это значение с числом, которое имеет нулевое значение, где вы хотите сохранить биты целыми, и тот, где вы хотите перевернуть эти биты.
Надеюсь, это поможет!
Вы всегда можете использовать std::bitset
, что упрощает модификацию бит.
Или вы можете использовать манипуляции с битами (при условии, что вы имеете в виду 4-й бит, подсчитывающий один. Не вычитайте 1, если вы имеете в виду подсчет от 0). Обратите внимание, что я использую 1U
только для того, чтобы гарантировать, что вся операция будет выполняться в неподписанных числах:
Чтобы установить: x |= (1U << (4 - 1));
Чтобы очистить: x &= ~(1U << (4 - 1));
Для переключения: x ^= (1U << (4 - 1));
Чтобы установить четвертый бит, OR
с 00001000
(двоичным).
Чтобы очистить четвертый бит, AND
с помощью 11110111
(двоичный).
Чтобы переключить четвертый бит, XOR
на 00001000
(двоичный).
Примеры:
00110010 ИЛИ 00001000 = 00111010
00110010 И 11110111 = 00110010
00110010 XOR 00001000 = 00111010
Попробуйте одну из этих функций на языке C изменить n бит
char bitfield;
// start at 0th position
void chang_n_bit(int n, int value)
{
bitfield = (bitfield | (1 << n)) & (~( (1 << n) ^ (value << n) ));
}
void chang_n_bit(int n, int value)
{
bitfield = (bitfield | (1 << n)) & ((value << n) | ((~0) ^ (1 << n)));
}
void chang_n_bit(int n, int value)
{
if(value)
bitfield |= 1 << n;
else
bitfield &= ~0 ^ (1 << n);
}
char print_n_bit(int n)
{
return (bitfield & (1 << n)) ? 1 : 0;
}
Просто, так как у вас есть или какое бы то ни было значение,
int x = 50;
Чтобы программно выбрать 4-й бит (справа),
int y = x | 0x00000008;
Вы можете использовать двоичные И и ИЛИ для переключения четвертого бита.
Чтобы установить четвертый бит в x, вы должны использовать x |= 1<<3;
, 1<<3
как левый сдвиг 0b0001 на три бита, производящий 0b1000.
Чтобы очистить четвертый бит от x, вы должны использовать x &= ~(1<<3);
, двоичный И между 0b00110010 (x) и (эффективно) 0b11110111, маскирующий каждый бит в x, который не находится в четвертом положении, тем самым очистив его.