Побитовое чтение для '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 в случае, если бит равен нулю?
@Cammack, 👍0
2 ответа
Лучший ответ:
Самый простой способ — просто замаскировать отдельный фрагмент, не делая никаких сдвигов:
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.
Есть альтернатива выполнению битовых сдвигов — использование макроса 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 |= bit (WDCE) | bit (WDE);
Это легче читать, чем:
WDTCSR |= (1 << WDCE) | (1 << WDE);
И гораздо проще, чем превращать их в шестнадцатеричные числа:
WDTCSR |= 0x10 | 0x08;
А если вам интересно, как немного прояснить ситуацию, вы и в дополнении 1:
WDTCSR &= ~bit (WDCE);
- Как устранить сообщение об ошибке "assignment of function 'void digitalWrite (uint8_t, uint_8)"?
- Получить массив символов с помощью модуля SIM900
- Считывание данных нескольких датчиков из текстового файла, расположенного на SD-карте в Arduino/ESP32
- Чтение двоичного файла на SD-карте
- Проблемы с Serial.read()
- Как запрограммировать 2 ультразвуковых датчика, один на серводвигателе и один прикрепленный на передней стороне автомобиля?
- Термистор не работает
- Занимают ли комментарии место в скомпилированном скетче C++? Ардуино / узел микроконтроллера