Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Как перевернуть значение одного бита?

Автор вопроса: user1909612Ответов: 4

Я буду честен, это домашнее задание, которое я просто не могу сделать. Задача состоит в том, чтобы обработать 8 разных флажков, используя один байт. Конструктор формы, которая содержит флажки, принимает байт в качестве входных данных и устанавливает флажки в положение "отмечено" на основе ввода. Затем байт флага где-то сохраняется, и после этого каждый раз, когда один флажок меняет свой статус (с отмеченного на непроверенный и с непроверенного на отмеченный), я должен соответствующим образом изменить байт флага. Пока смог сделать только первую часть:

public Form1(byte flags)
{
    InitializeComponent();
    flags2 = flags;
    if ((flags & 0x01) >> 0 != 0) checkBox1.Checked = true;
    if ((flags & 0x02) >> 1 != 0) checkBox2.Checked = true;
    if ((flags & 0x04) >> 2 != 0) checkBox3.Checked = true;
    if ((flags & 0x08) >> 3 != 0) checkBox4.Checked = true;
    if ((flags & 0x10) >> 4 != 0) checkBox4.Checked = true;
    if ((flags & 0x20) >> 5 != 0) checkBox6.Checked = true;
    if ((flags & 0x40) >> 6 != 0) checkBox7.Checked = true;
    if ((flags & 0x80) >> 7 != 0) checkBox8.Checked = true;
}

Но я действительно не знаю, как сделать не только 1 бит. Я думал об использовании дополнений, но тогда остальные меняют биты влево. Я могу использовать этот трюк только в самом важном месте, где отдых не имеет последствий.

private void checkBox8_CheckedChanged(object sender, EventArgs e)
{
    flags2 += 0x80;
}

Для других битов я действительно мог бы использовать некоторую помощь.

winformsbit-manipulationbitwise-operators

Ответы

Ответ 1 · рейтинг 1 · joe

Вы должны инвертировать битовую маску:

flags &= ~0x10

установит бит 4 (0x10) в 0.
Оператор ~ инвертирует все биты (пример 8 бит):

 0x10 (0001000)
~0x10 (1110111)

Чтобы немного переключить, используйте это (xor):

flags ^= 0x10

Использование сложений никогда не работает, если вы хотите работать с битами.
Для практики я рекомендую записывать все числа в виде битовых масок: 0x10 = 0001000 (основание 2)

Ответ 2 · рейтинг 2 · Michael Gunter

Для переключения битов используйте оператор XOR (^):

flags ^= <bits>;   -or-  flags2 = flags ^ <bits>;   -e.g.-  flags ^= 0x04;

Чтобы установить биты, используйте оператор ИЛИ (|):

flags |= <bits>;   -or-  flags2 = flags | <bits>;   -e.g.-  flags |= 0x08;

Чтобы очистить биты, используйте оператор И (&) и оператор НЕ (~).

flags &= ~<bits>;  -or-  flags2 = flags & ~<bits>;  -e.g.-  flags &= ~0x08;

Ответ 3 · рейтинг 1 · Steve

Предположим, что переменная, в которой вы сохранили начальный статус, имеет значение flags2, тогда

private void CheckBox1_CheckedChanged(Object sender, EventArgs e)
{
   if(checkBox1.Checked)
       flags2 |= 1;
   else
       flags2 &= ~0xFE;

   // ~0x2=0xFD, ~0x4=0xFB, ~0x08=0xF7,
   // ~0x10=0xF5, ~0x20=0xEB, ~0x40=0xD7, ~0x80=0xAF
}

Также обратите внимание, что ваш первоначальный тест можно было бы переписать просто как

if ((flags & 0x04) != 0) checkBox1.Checked = true;

Ответ 4 · Michael Gunter

Кроме того, вы можете упростить код инициализации:

checkBox1.Checked = ((flags & 0x01) != 0);
checkBox2.Checked = ((flags & 0x02) != 0);
checkBox3.Checked = ((flags & 0x04) != 0);
checkBox4.Checked = ((flags & 0x08) != 0);
checkBox5.Checked = ((flags & 0x10) != 0);
checkBox6.Checked = ((flags & 0x20) != 0);
checkBox7.Checked = ((flags & 0x40) != 0);
checkBox8.Checked = ((flags & 0x80) != 0);

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы