Побітове “і” (&), побітове “або” (|), побітове виключальне “або” (^)

Документація
Побітові оператори виконують обчислення на бітовому рівні змінних. Вони допомагають вирішувати широке коло поширених проблем програмування.

Побітове “і” (&)

Побітовий оператор “і” в C++ (одиничний амперсанд — &) використовується між двома іншими цілими виразами. Побітове “і” керує кожною бітовою позицією довколишнього виразу незалежно, керуючись таким правилом: якщо обидва вхідних біти дорівнюють 1, то результат дорівнює 1, в іншому випадку вихід дорівнює 0. Інший спосіб виразити це:

0  0  1  1    operand1
 0  1  0  1    operand2
 ----------
 0  0  0  1    (operand1 & operand2) - результат


В Arduino тип int має 16-бітове значення, тому використання & між двома виразами int спричиняє виконання шістнадцяти операцій “і”. У фрагменті коду це виглядає так:

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


Кожен з 16 бітів в a та b обробляються з використанням побітового “і”, всі 16 бітів результату зберігаються в c. Отримане значення становить 01000100 у двійковій системі, що складає 68 у десятковій системі.

Одним з найпоширеніших застосувань побітового “і” є вибір конкретного біта (або бітів) з цілочисельного значення, яке часто називають маскуванням. Дивіться приклад нижче.

Побітове “чи” (|)

Побітовий оператор “чи” у C++ позначається вертикальною рискою (|). Як і оператор “і”, оператор “чи” керує кожним бітом незалежно в двох навколишніх цілочисельних виразах, але що він робить, звісно ж, відрізняється. Побітове “чи” видає одиницю, якщо обидва або будь-який один з двох бітів видає одиницю, в іншому випадку видає нуль. Іншими словами:

0  0  1  1    operand1
0  1  0  1    operand2
----------
0  1  1  1    (operand1 | operand2) - результат


Нижче представлено використання побітового “чи” у фрагменті коду C++:

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


Приклад для Arduino Uno

Поширеним застосуванням побітових операторів “і” та “чи” є, як його називають програмісти, читання-модифікація-запис в порт. На мікроконтролерах портом є 8-бітне число, яке відображає стан пінів. Запис в порт контролює всі контакти відразу.

PORTD — це вбудована константа, яка відсилає до вихідних значень пінів 0,1,2,3,4,5,6,7. Якщо є одиниця в позиції біта, то значення піна HIGH. (Піни вже мають бути налаштовані як виходи командою pinMode()). Отже, якщо ми напишемо PORTD = B00110001, у пінів 0, 4 та 5 буде значення HIGH. Одна невелика заковика полягає в тому, що ми також могли змінити стан пінів 0 та 1, які використовуються Arduino для послідовного зв’язку, тому ми могли йому завадити.

Алгоритм програми такий:

  • Отримати PORTD і очистити тільки біти, що відповідають пінам, якими ми хочемо управляти (з побітовим “і”).
  • Сполучити змінене значення PORTD з новим значенням підконтрольних пінів (з побітовим “чи”).

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);
   }
}


Побітове заперечне “чи” (^)

Є один незвичний оператор у C++ під назвою побітове виключне або заперечне “чи”, який позначається ^. Цей оператор дуже схожий до побітового оператора “чи”, тільки він визначає задану бітову позицію як 0, якщо обидва вхідні біти для цієї позиції становлять 1.

0  0  1  1    operand1
 0  1  0  1    operand2
 ----------
 0  1  1  0    (operand1 ^ operand2) - результат


Інший спосіб розглянути заперечне “чи”: кожен біт в результаті дає одиницю, якщо вхідні біти різні, або 0, якщо однакові.

Ось простий приклад коду:

int x = 12;     // у двійковій системі: 1100
int y = 10;     // у двійковій системі: 1010
int z = x ^ y;  // у двійковій системі: 0110, або 6 у десятковій


Оператор ^ часто використовується для перемикання (тобто переходу від 0 до 1 або від 1 до 0) деяких бітів в цілому виразі. В побітовій операції “або”, якщо є 1 у біті маски, то біт інвертується. Якщо є 0, біт не інвертується і залишається таким самим. Програма нижче змушує мигати цифровий пін 5.

// Blink_Pin_5
// зразок для побітового заперечного “чи”
void setup(){
DDRD = DDRD | B00100000; // налаштувати цифровий пін 5 як вихід
Serial.begin(9600);
}

void loop(){
PORTD = PORTD ^ B00100000;  // інвертувати біт 5 (цифровий пін 5), інші залишити непорушними
delay(100);
}


Повернутись до головної

Коментарі 0

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.