Побитовое чтение для 'FALSE'

В скетче, над которым я работаю, я сохраняю несколько 1-битных значений, представляющих различные логические состояния, в одном байте, пытаясь сэкономить драгоценную оперативную память. (пример для 5 булевых состояний: dec10 = b00001010, пять состояний: 0, 1, 0, 1, 0)

Затем я использую оператор if, чтобы определить, является ли соответствующий бит TRUE или FALSE:
если ((параметры>>3) & 1 == 1)

Вышеуказанное выражение оценит значение true, когда соответствующий бит равен 1, поэтому, если я захочу что-то выполнить в этом случае, отлично, нет проблем!

Однако если я хочу, чтобы мой оператор if оценивал TRUE в том случае, если соответствующий бит равен 0, я не могу понять, какой код мне нужен.


Я подумал, что проблема может заключаться в том, что другие «не относящиеся к делу» биты мешают, поэтому я попробовал сместить младший бит полностью в позицию старшего бита, а затем снова сместиться в младший бит:
если ((параметры<<4>>7) & 1 == 0)
но это все еще не то, чего я пытаюсь добиться (и, похоже, создает большую нагрузку на процессор).

Также такое чувство, что я перепробовал почти все возможные комбинации ~&0, !&0, ==0, !=0, ~&1, !&1, ==1, !=1, но, должно быть, я что-то упустил...

Может ли кто-нибудь сказать мне, как заставить оператор if возвращать значение true в случае, если бит равен нулю?

, 👍0


2 ответа


Лучший ответ:

4

Самый простой способ — просто замаскировать отдельный фрагмент, не делая никаких сдвигов:

if (options & 0x04) {
    // Сделать что-нибудь, если правда
} else {
    // Сделать что-нибудь, если ложно
}

Или, если перевернуть:

if (!(options & 0x04)) {
    // Сделать что-нибудь, если ложно
} else {
    // Сделать что-нибудь, если это правда.
}

В языке C всё дело в том, что 0 — это ложь, а всё остальное — истина. Поэтому, если ваша переменная options содержит 0b00001010, и вы выполняете операцию AND с 0x04 (что в шестнадцатеричном формате соответствует 0b00001000), то в результате получится 0b00001000. Это 0x04, что отлично от 0, поэтому оно истинно.

Если options содержит 0b00000010 и вы выполняете операцию AND с 0x04, вы получите 0b00000000, что равно 0. Поскольку 0 — это false, результат — false.

Вам все равно, какое именно число — вас волнует только, равно ли оно 0.

,

2

Есть альтернатива выполнению битовых сдвигов — использование макроса bit, который определен в Arduino.h (и, следовательно, доступен автоматически).

#define bit(b) (1UL << (b))

Теперь, если вы хотите проверить, установлен ли второй бит (который в качестве маски будет 0x04, т.е. 1, сдвинутая влево 2 раза), вы можете сделать следующее:

if (options & bit (2))
   {
   // бит номер 2 установлен
   }
else
   {
   // бит номер 2 очищен
   }

Это легче читать, чем:

if (options & (1 << 2))

или:

if (options & 0x04)

И чтобы инвертировать это:

if (!(options & bit (2)))
   {
   // бит номер 2 очищен
   }

Или:

if ((options & bit (2)) == 0)
   {
   // бит номер 2 очищен
   }

Кроме того, различные биты процессора указаны в виде номеров битов в файлах включения Atmega (а не в виде битовых масок).

Регистр WDTCSR

Так, например, чтобы установить некоторые биты процессора, вы можете сделать это:

WDTCSR |= bit (WDCE) | bit (WDE);

Это легче читать, чем:

WDTCSR |= (1 << WDCE) |  (1 << WDE);

И гораздо проще, чем превращать их в шестнадцатеричные числа:

WDTCSR |= 0x10 | 0x08;

А если вам интересно, как немного прояснить ситуацию, вы и в дополнении 1:

WDTCSR &= ~bit (WDCE);
,