Недоліки операторів бітового рівня.
Ви запитаєте:
«Чи є якась - або причина не використовувати оператори побітового &
, |
і ^
для" BOOL "значень в C ++? "
Так, логічні оператори , тобто вбудовані логічні оператори високого рівня !
, &&
і ||
пропонують такі переваги:
Гарантоване перетворення аргументів у bool
, тобто в 0
і 1
порядкове значення.
Гарантована оцінка короткого замикання, коли оцінка виразу припиняється, як тільки стане відомий кінцевий результат.
Це можна інтерпретувати як логіку дерева-значення, з True , False та невизначеним .
Прочитані текстові еквіваленти not
, and
і or
навіть якщо я сам їх не використовую.
Як читач Сурма зазначає в коментарі також bitlevel оператори мають альтернативні маркери, а саме bitand
, bitor
, xor
і compl
, але , на мою думку , це менш читаються , ніж and
, or
і not
.
Простіше кажучи, кожна така перевага операторів високого рівня є недоліком операторів бітового рівня.
Зокрема, оскільки побітовим операторам не вистачає перетворення аргументів на 0/1, ви отримуєте, наприклад, 1 & 2
→ 0
, в той час як 1 && 2
→ true
. Крім того ^
, порозрядний ексклюзив або може неправильно поводитись таким чином. Логічні значення 1 і 2 розглядаються однаково, а саме true
, але розглядаються як бітові шаблони, вони різні.
Як висловити логічне або / або на C ++.
Потім ви надаєте трохи передумов для питання,
"Я іноді стикаюся з ситуаціями, коли я хочу, щоб саме одна з двох умов була істинною (XOR), тому я просто вкидаю оператор ^ в умовний вираз."
Ну, побітові оператори мають вищий пріоритет, ніж логічні оператори. Це, зокрема, означає, що в змішаному вираженні, як-от
a && b ^ c
ви отримуєте, можливо, несподіваний результат a && (b ^ c)
.
Натомість пишіть просто
(a && b) != c
висловлюючи більш стисло, що ви маєте на увазі.
Для множинного аргументу або / або не існує оператора C ++, який виконує цю роботу. Наприклад, якщо ви пишете a ^ b ^ c
, це не вираз, який говорить "або a
, b
або c
правда". Замість цього він говорить, «непарне число a
, b
і c
істинно», які могли б бути 1 з них або всіх 3 ...
Щоб висловити загальне або / або коли a
, b
і c
мають тип bool
, просто напишіть
(a + b + c) == 1
або, не bool
аргументуючи, перетворити їх на bool
:
(!!a + !!b + !!c) == 1
Використання &=
для накопичення булевих результатів.
Ви далі розробляєте,
"Мені також потрібно іноді накопичувати булеві значення, &=
і це |=?
може бути дуже корисно".
Ну, це відповідає перевірці, чи виконуються відповідно всі чи будь-які умови, а закон де Моргана підказує, як переходити від одного до іншого. Тобто вам потрібен лише один з них. Ви в принципі можете використовувати *=
як &&=
-оператора (адже, як виявив старий добрий Джордж Бул, логічне І дуже легко можна виразити як множення), але я думаю, що це заплутає і, можливо, введе в оману тих, хто підтримує код.
Розглянемо також:
struct Bool
{
bool value;
void operator&=( bool const v ) { value = value && v; }
operator bool() const { return value; }
};
#include <iostream>
int main()
{
using namespace std;
Bool a = {true};
a &= true || false;
a &= 1234;
cout << boolalpha << a << endl;
bool b = {true};
b &= true || false;
b &= 1234;
cout << boolalpha << b << endl;
}
Вихідні дані з Visual C ++ 11.0 та g ++ 4.7.1:
правда
помилковий
Причина різниці в результатах полягає в тому, що рівень рівня &=
не забезпечує перетворення bool
аргументу правої сторони.
Отже, який із цих результатів ви бажаєте використовувати &=
?
Якщо перше, true
то краще визначте оператор (наприклад, як зазначено вище) або іменовану функцію, або використовуйте явне перетворення виразу праворуч, або напишіть оновлення повністю.