Arduino:Справочник языка Arduino/Побитовые операторы/AND(&),OR и XOR (^): различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
 
(не показано 5 промежуточных версий этого же участника)
Строка 5: Строка 5:
=Побитовые операторы AND (&), OR (|) и XOR (^)<ref>[https://www.arduino.cc/en/Reference/BitwiseAnd Bitwise AND (&), Bitwise OR (|), Bitwise XOR (^)]</ref>=
=Побитовые операторы AND (&), OR (|) и XOR (^)<ref>[https://www.arduino.cc/en/Reference/BitwiseAnd Bitwise AND (&), Bitwise OR (|), Bitwise XOR (^)]</ref>=


Побитовые операторы выполняют свои расчет на уровне битов. Они помогают решать широкий спектр типовых программистских задач. Большая часть изложенного ниже материала взята из отличного руководства о побитовых расчетах, которое можно найти [http://playground.arduino.cc/Code/BitMath по этой ссылке].
Побитовые операторы выполняют свои расчет на уровне [[бит]]ов. Они помогают решать широкий спектр типовых программистских задач. Большая часть изложенного ниже материала взята из отличного руководства о побитовых расчетах, которое можно найти [http://playground.arduino.cc/Code/BitMath по этой ссылке].


==Описание и синтаксис==
==Описание и синтаксис==
Строка 13: Строка 13:
===Побитовый оператор AND (&)===
===Побитовый оператор AND (&)===


В языке '''C++''' этот оператор обозначается символом '''«&»''', т.е. одинарным амперсандом. Он ставится между двумя целочисленными выражениями и работает с каждым битом по отдельности, руководствуясь следующим правилом: если оба бита равны '''«1»''', результатом тоже будет '''«1»''', а если хотя бы один из битов равен '''«0»''', то результатом будет '''«0»'''. Впрочем, это можно выразить и так:
В языке [[C++]] этот оператор обозначается символом «&», т.е. одинарным амперсандом. Он ставится между двумя целочисленными выражениями и работает с каждым битом по отдельности, руководствуясь следующим правилом: если оба бита равны «1», результатом тоже будет «1», а если хотя бы один из битов равен «0», то результатом будет «0». Впрочем, это можно выразить и так:


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
0  0  1  1    operand1
0  0  1  1    operand1
0  1  0  1    operand2
0  1  0  1    operand2
Строка 22: Строка 22:
</syntaxhighlight>
</syntaxhighlight>


В '''Arduino''' используются, как правило '''16-битные значения''', то есть, если поставить этот оператор между двумя выражениями, он произведет поиск сходств '''между 16-тью парами битов'''. Это может выглядеть примерно так:
В [[Arduino]] используются, как правило 16-битные значения, то есть, если поставить этот оператор между двумя выражениями, он произведет поиск сходств между 16-тью парами битов. Это может выглядеть примерно так:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
int a =  92;    // в бинарном виде: 0000000001011100
int a =  92;    // в бинарном виде: 0000000001011100
int b = 101;    // в бинарном виде: 0000000001100101
int b = 101;    // в бинарном виде: 0000000001100101
Строка 30: Строка 30:
</syntaxhighlight>
</syntaxhighlight>


Таким образом, побитовый '''AND''' обработает '''все 32 бита''' в выражениях '''а и b''', а '''итоговые 16 бит''' будут записаны в выражение '''c'''. Оно будет равняться '''01000100''', что в десятичном выражении означает '''«68»'''.
Таким образом, побитовый [[AND]] обработает все 32 бита в выражениях а и b, а итоговые 16 бит будут записаны в выражение c. Оно будет равняться 01000100, что в десятичном выражении означает «68».


Одно из самых распространенных применений побитового '''AND''' — это вычленение отдельного бита (или битов) из числа других битов, находящихся в целочисленном значении, что часто называют «маскированием». Пример можно найти ниже.
Одно из самых распространенных применений [[побитового AND]] — это вычленение отдельного бита (или битов) из числа других битов, находящихся в целочисленном значении, что часто называют «маскированием». Пример можно найти ниже.


===Побитовый OR===
===Побитовый OR===


Этот оператор обозначается в '''C++''' символом вертикальной черты, т.е. '''«|»'''. Как и '''«&»''', он используется для обработки двух целочисленных выражений и работает с каждым битом по отдельности, но его функция в другом — если один или два бита в паре равны '''«1»''', то итоговым битом будет '''«1»''', а если оба бита будут равны '''«0»''', то итоговым будет '''«0»'''. Другими словами:
Этот оператор обозначается в [[C++]] символом вертикальной черты, т.е. «|». Как и «&», он используется для обработки двух целочисленных выражений и работает с каждым битом по отдельности, но его функция в другом — если один или два бита в паре равны «1», то итоговым битом будет «1», а если оба бита будут равны «0», то итоговым будет «0». Другими словами:


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
0  0  1  1    operand1
0  0  1  1    operand1
0  1  0  1    operand2
0  1  0  1    operand2
Строка 45: Строка 45:
</syntaxhighlight>
</syntaxhighlight>


Вот пример использования побитового '''OR''' в кусочке кода '''C++''':
Вот пример использования побитового [[OR]] в кусочке кода [[C++]]:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
int a =  92;    // в бинарном виде: 0000000001011100
int a =  92;    // в бинарном виде: 0000000001011100
int b = 101;    // в бинарном виде: 0000000001100101
int b = 101;    // в бинарном виде: 0000000001100101
Строка 55: Строка 55:
====Пример программы для Arduino Uno====
====Пример программы для Arduino Uno====


Побитовые '''AND''' и '''OR''' чаще всего используются для так называемых операций '''«чтения-модификации-записи»''' при работе с портами. На микроконтроллерах порт — это '''8-битное число''', которое отображает некие данные о состоянии контактов.  
Побитовые AND и OR чаще всего используются для так называемых операций «чтения-модификации-записи» при работе с портами. На микроконтроллерах порт — это 8-битное число, которое отображает некие данные о состоянии контактов.  


Таким образом, меняя это «портовое» число, мы можем управлять всеми контактами разом.
Таким образом, меняя это «портовое» число, мы можем управлять всеми контактами разом.


'''PORTD''' – это встроенная константа, отображающая внешние состояния цифровых контактов '''0, 1, 2, 3, 4, 5, 6 и 7'''. То есть, если какой-то бит содержит в себе значение '''«1»''', значит соответствующий контакт находится в положении [[Arduino:Справочник языка Arduino/Константы/HIGH|HIGH]].  
PORTD – это встроенная константа, отображающая внешние состояния цифровых контактов 0, 1, 2, 3, 4, 5, 6 и 7. То есть, если какой-то бит содержит в себе значение «1», значит соответствующий контакт находится в положении [[Arduino:Справочник языка Arduino/Константы/HIGH|HIGH]].  


Учтите, что эти контакты предварительно нужно настроить на [[Arduino:Справочник языка Arduino/Константы/OUTPUT|OUTPUT]] при помощи команды [[Arduino:Справочник языка Arduino/Функции/Цифровой ввод/вывод/pinMode()|pinMode()]]. Таким образом, если мы сделаем запись '''PORTD = B00110001;''' то переключим контакты '''0, 4 и 5''' в значение [[Arduino:Справочник языка Arduino/Константы/HIGH|HIGH]]. Но есть и затруднение — используя побитовые операторы, мы можем поменять значения контактов '''0 и 1''', которые используются '''Arduino''' для последовательной передачи данных, и тем самым нарушить ее работу.
Учтите, что эти контакты предварительно нужно настроить на [[Arduino:Справочник языка Arduino/Константы/OUTPUT|OUTPUT]] при помощи команды [[Arduino:Справочник языка Arduino/Функции/Цифровой ввод/вывод/pinMode()|pinMode()]]. Таким образом, если мы сделаем запись PORTD = B00110001; то переключим контакты 0, 4 и 5 в значение [[Arduino:Справочник языка Arduino/Константы/HIGH|HIGH]]. Но есть и затруднение — используя побитовые операторы, мы можем поменять значения контактов 0 и 1, которые используются Arduino для последовательной передачи данных, и тем самым нарушить ее работу.


Алгоритм у нашей программы будет следующий:
Алгоритм у нашей программы будет следующий:


* Берем '''PORTD''' и выбираем биты, отвечающие за контакты, которыми мы хотим управлять (при помощи побитового '''AND''')
* Берем PORTD и выбираем биты, отвечающие за контакты, которыми мы хотим управлять (при помощи побитового AND)
* Комбинируем модифицированный '''PORTD''' с новым значением для находящихся под управлением контактов (при помощи побитового '''OR''')
* Комбинируем модифицированный PORTD с новым значением для находящихся под управлением контактов (при помощи побитового OR)


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
int i;    // переменная-счетчик
int i;    // переменная-счетчик
int j;
int j;
Строка 92: Строка 92:
===Побитовый XOR (^)===
===Побитовый XOR (^)===


В языке '''C++''' есть один необычный оператор, который называется '''«побитовый EXCLUSIVE OR»''', также известный как '''«побитовый XOR»'''. Отображается от символом вставки или '''«^»'''. Он очень похож на побитовый '''OR''', но его отличие в том, что он дает '''«0»''', если оба бита в паре равны '''«1»'''.
В языке [[C++]] есть один необычный оператор, который называется «побитовый EXCLUSIVE OR», также известный как «побитовый XOR». Отображается от символом вставки или «^». Он очень похож на побитовый [[OR]], но его отличие в том, что он дает «0», если оба бита в паре равны «1».


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
0  0  1  1    operand1
0  0  1  1    operand1
0  1  0  1    operand2
0  1  0  1    operand2
Строка 101: Строка 101:
</syntaxhighlight>
</syntaxhighlight>


Или, другими словами, побитовый '''XOR''' использует следующее правило: он дает '''«1»''', если биты в паре друг от друга отличаются, и дает '''«0»''', если они одинаковы.
Или, другими словами, побитовый [[XOR]] использует следующее правило: он дает «1», если биты в паре друг от друга отличаются, и дает «0», если они одинаковы.


Вот небольшой кусочек кода с использованием '''XOR''':
Вот небольшой кусочек кода с использованием [[XOR]]:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
int x = 12;    // в бинарном виде: 1100
int x = 12;    // в бинарном виде: 1100
int y = 10;    // в бинарном виде: 1010
int y = 10;    // в бинарном виде: 1010
Строка 111: Строка 111:
</syntaxhighlight>
</syntaxhighlight>


Оператор '''«^»''' часто используется для того, чтобы поменять некоторые биты в целочисленном выражении с одного на другой (т.е. с '''«0»''' на '''«1»''' или с '''«1»''' на '''«0»'''). Ниже — программа для «перетасовки» битов на '''5-ом цифровом контакте'''.
Оператор «^» часто используется для того, чтобы поменять некоторые биты в целочисленном выражении с одного на другой (т.е. с «0» на «1» или с «1» на «0»). Ниже — программа для «перетасовки» битов на 5-ом цифровом контакте.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
// Blink_Pin_5
// Blink_Pin_5
// пример для демонстрации побитового оператора Exclusive OR
// пример для демонстрации побитового оператора Exclusive OR
Строка 128: Строка 128:


=См.также=
=См.также=
{{ads}}
 
# [[Arduino:Справочник языка Arduino/Логические операторы/&& (И)|&& (И)]]
# [[Arduino:Справочник языка Arduino/Логические операторы/&& (И)|&& (И)]]
# [[Arduino:Справочник языка Arduino/Логические операторы/ ИЛИ | ИЛИ]]
# [[Arduino:Справочник языка Arduino/Логические операторы/ ИЛИ | ИЛИ]]
Строка 136: Строка 136:
<references />
<references />


{{Навигационная таблица/Справочник языка Arduino}}
{{Навигационная таблица/Портал/Arduino}}
{{Навигационная таблица/Arduino библиотеки}}


[[Категория:Справочник языка Arduino]]
[[Категория:Справочник языка Arduino]]
[[Категория:Побитовые операторы языка Arduino]]
[[Категория:Побитовые операторы языка Arduino]]
[[Категория:Побитовый оператор]]
[[Категория:Побитовый оператор]]

Текущая версия от 08:33, 25 февраля 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Побитовые операторы AND (&), OR (|) и XOR (^)[1]

Побитовые операторы выполняют свои расчет на уровне битов. Они помогают решать широкий спектр типовых программистских задач. Большая часть изложенного ниже материала взята из отличного руководства о побитовых расчетах, которое можно найти по этой ссылке.

Описание и синтаксис

Ниже — описание и синтаксис всех этих операторов. Более подробно о каждом из них можно прочесть в вышеуказанном руководстве.

Побитовый оператор AND (&)

В языке C++ этот оператор обозначается символом «&», т.е. одинарным амперсандом. Он ставится между двумя целочисленными выражениями и работает с каждым битом по отдельности, руководствуясь следующим правилом: если оба бита равны «1», результатом тоже будет «1», а если хотя бы один из битов равен «0», то результатом будет «0». Впрочем, это можно выразить и так:

0  0  1  1    operand1
0  1  0  1    operand2
----------
0  0  0  1    (operand1 & operand2)  итоговый результат

В Arduino используются, как правило 16-битные значения, то есть, если поставить этот оператор между двумя выражениями, он произведет поиск сходств между 16-тью парами битов. Это может выглядеть примерно так:

int a =  92;    // в бинарном виде: 0000000001011100
int b = 101;    // в бинарном виде: 0000000001100101
int c = a & b;  // результат:       0000000001000100, или 68 в десятичном виде.

Таким образом, побитовый AND обработает все 32 бита в выражениях а и b, а итоговые 16 бит будут записаны в выражение c. Оно будет равняться 01000100, что в десятичном выражении означает «68».

Одно из самых распространенных применений побитового AND — это вычленение отдельного бита (или битов) из числа других битов, находящихся в целочисленном значении, что часто называют «маскированием». Пример можно найти ниже.

Побитовый OR

Этот оператор обозначается в C++ символом вертикальной черты, т.е. «|». Как и «&», он используется для обработки двух целочисленных выражений и работает с каждым битом по отдельности, но его функция в другом — если один или два бита в паре равны «1», то итоговым битом будет «1», а если оба бита будут равны «0», то итоговым будет «0». Другими словами:

0  0  1  1    operand1
0  1  0  1    operand2
----------
0  1  1  1    (operand1 | operand2)  итоговый результат

Вот пример использования побитового OR в кусочке кода C++:

int a =  92;    // в бинарном виде: 0000000001011100
int b = 101;    // в бинарном виде: 0000000001100101
int c = a | b;  // результат:       0000000001111101, или 125 в десятичном виде.

Пример программы для Arduino Uno

Побитовые AND и OR чаще всего используются для так называемых операций «чтения-модификации-записи» при работе с портами. На микроконтроллерах порт — это 8-битное число, которое отображает некие данные о состоянии контактов.

Таким образом, меняя это «портовое» число, мы можем управлять всеми контактами разом.

PORTD – это встроенная константа, отображающая внешние состояния цифровых контактов 0, 1, 2, 3, 4, 5, 6 и 7. То есть, если какой-то бит содержит в себе значение «1», значит соответствующий контакт находится в положении HIGH.

Учтите, что эти контакты предварительно нужно настроить на OUTPUT при помощи команды pinMode(). Таким образом, если мы сделаем запись PORTD = B00110001; то переключим контакты 0, 4 и 5 в значение HIGH. Но есть и затруднение — используя побитовые операторы, мы можем поменять значения контактов 0 и 1, которые используются Arduino для последовательной передачи данных, и тем самым нарушить ее работу.

Алгоритм у нашей программы будет следующий:

  • Берем PORTD и выбираем биты, отвечающие за контакты, которыми мы хотим управлять (при помощи побитового AND)
  • Комбинируем модифицированный PORTD с новым значением для находящихся под управлением контактов (при помощи побитового OR)
int i;     // переменная-счетчик
int j;

void setup(){
DDRD = DDRD | B11111100; // задаем направляющие биты для контактов 2-7; 0 и 1 не трогаем (xx | 00 == xx)
// то же, что и pinMode(pin, OUTPUT) для контактов 2-7
Serial.begin(9600);
}

void loop(){
for (i=0; i<64; i++){

PORTD = PORTD & B00000011;  // вычленяем биты 2-7, контакты 0 и 1 не трогаем (xx & 11 == xx)
j = (i << 2);               // перемещаемся на две позиции — сразу к контактам 2-7 (чтобы избежать контактов 0 и 1)
PORTD = PORTD | j;          // комбинируем информацию на порте с новой информацией для LED-контактов
Serial.println(PORTD, BIN); // показываем маскировку (для отладки)
delay(100);
   }
}

Побитовый XOR (^)

В языке C++ есть один необычный оператор, который называется «побитовый EXCLUSIVE OR», также известный как «побитовый XOR». Отображается от символом вставки или «^». Он очень похож на побитовый OR, но его отличие в том, что он дает «0», если оба бита в паре равны «1».

0  0  1  1    operand1
0  1  0  1    operand2
----------
0  1  1  0    (operand1 ^ operand2)  итоговый результат

Или, другими словами, побитовый XOR использует следующее правило: он дает «1», если биты в паре друг от друга отличаются, и дает «0», если они одинаковы.

Вот небольшой кусочек кода с использованием XOR:

int x = 12;     // в бинарном виде: 1100
int y = 10;     // в бинарном виде: 1010
int z = x ^ y;  // в бинарном виде: 0110, или в десятичном: 6

Оператор «^» часто используется для того, чтобы поменять некоторые биты в целочисленном выражении с одного на другой (т.е. с «0» на «1» или с «1» на «0»). Ниже — программа для «перетасовки» битов на 5-ом цифровом контакте.

// Blink_Pin_5
// пример для демонстрации побитового оператора Exclusive OR
void setup(){
DDRD = DDRD | B00100000; // задаем 5-ый цифровой контакт как OUTPUT 
Serial.begin(9600);
}

void loop(){
PORTD = PORTD ^ B00100000;  // инвертируем 5-ый бит (5-ый цифровой контакт), остальные не трогаем
delay(100);
}

См.также

  1. && (И)
  2. ИЛИ

Внешние ссылки