Страницы

Поиск по вопросам

понедельник, 25 марта 2019 г.

Зачем использовать “|=”, “&=” и т.п. в C++ вместо “=”?

Програмлю Arduino и читаю в интернете про PORT. Говорят, что какая-то там стабильность будет, если писать вместо = - |=, или &=. Так я так и не понял, для чего так писать и чем это отличается от обычного "равно"? Вот пример рабочего кода:
int main() {
DDRB = B00100000;
while(1) { PORTB |= B00100000; delay(1000); PORTB &= B00000000; delay(1000); } }
Если заменить все эти |=, и &= на =, то всё будет работать точно также (как мне кажется) и даже не изменится размер прошивки (скетча). Так возвращаемся к вопросу: Зачем "|=", "&=" и т.д. в c++?


Ответ

Если вопрос касается именно c++ - то это операторы.
|= - побитовое или с присвоением. &= - побитовое и с присвоением.
Подробнее про операторы тут
По сути, это упрощенный синтаксис для подобной записи:
a = a | b; // для |= a = a & b; // для &=
Думаю, стало немного яснее, при чем тут равно. Далее попробуем разобраться, для чего же сами операторы | и &. Они называются побитовое или и побитовое и соответственно.
Оператор | берет побитовое представление операндов, и в результате выполнения этого оператора вы получите число, побитовое представление которого будет содержать единицы на тех позициях, на которых хоть в одном из двух побитовых представлений операндов стояла единица. Например:
4 | 5 = 5; // или (в побитовом представлении) 100 | 101 = 101;
Заметим, что крайняя слева и справа единицы есть хоть в одном из двоичных представлений чисел, и поэтому после выполнения побитового или у нас есть число 101 (в бинарном представлении) или 5 (в десятичной системе счисления).
Оператор & берет побитовое представления операндов, и в результате выполнения этого оператора вы получите число, побитовое представление которого будет содержать единицы на тех позициях, на которых в обоих побитовых представлениях операндов стояли единицы. Например:
4 & 5 = 4; // или (в побитовом представлении) 100 | 101 = 100;
Заметим, что осталась лишь одна единица, которая есть и в первом, и в правом операнде.
Ну и совсем вплотную подойдя к вашей задаче - | и & применяются обычно для работы с побитовыми флагами. Это сделано для экономии места. К примеру, у вас есть переменная размером 4 байта или 32 бита. В таком случае в этой переменной можно хранить аж 32 флага.
Чтобы добавить флаг, нужно применить |
int flags = 0; // Добавим флаг на третьей справа позиции, ведь бинарное представление 4 - 100 flags |= 0x4;
Чтобы проверить, есть ли флаг, нужно применить &
// Бинарное и - по сути маска. И если на этой позиции была 1, // то результат будет отличен от 0 и условие будет верным if (flags & 0x4) { // сделать что-то }
Как-то так. Почему же работает с равно? Все просто. С равно вы по сути стираете предыдущее состояние переменной с флагами, и передаете ей только 1 флаг вместе с равно. Надеюсь, понятно объяснил...
UPD кстати, в вашем случае PORTB |= B00100000; добавляет флаг, а потом PORTB &= B00000000; убирает его (что логично, ведь на той позиции, на которой мы поставили флаг, в B00000000 единицы нет, и применив и мы по сути убрали флажок).
UPD2 кстати, в чистом c++ нет литералов вида B00000000, это фишка компилятора arduino. В c++ начиная с версии 14 можно использовать запись вида 0b00000000, чтобы представить бинарный литерал.

Комментариев нет:

Отправить комментарий