Недоліки операторів бітового рівня.
Ви запитаєте:
«Чи є якась - або причина не використовувати оператори побітового &, |і ^для" 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то краще визначте оператор (наприклад, як зазначено вище) або іменовану функцію, або використовуйте явне перетворення виразу праворуч, або напишіть оновлення повністю.