Wady operatorów poziomów bitowych.
Ty pytasz:
„Czy jest jakiś powód, aby nie używać operatory bitowe &, |i ^dla«bool»wartości w C ++? ”
Tak, operatory logiczne , że jest wbudowany w wysokiego szczebla operatorów logicznych !, &&a ||oferują następujące zalety:
Gwarantowana konwersji argumentów do bool, czyli 0i 1wartości porządkowej.
Gwarantowana ocena zwarcia, w której ocena wyrażenia zatrzymuje się, gdy tylko znany jest wynik końcowy.
Można to zinterpretować jako logikę wartości drzewa, z True , False i Indeterminate .
Czytelne odpowiedniki tekstowe not, anda ornawet jeśli nie będę z nich korzystać siebie.
Jako czytelnik antymonu zauważa w komentarzu też bitlevel operatorzy mają alternatywne znaki, a mianowicie bitand, bitor, xori compl, ale moim zdaniem są mniej czytelne niż and, ori not.
Mówiąc najprościej, każda taka zaleta operatorów wysokiego poziomu jest wadą operatorów bitlevel.
W szczególności, ponieważ operatory bitowe nie mają konwersji argumentów na 0/1, otrzymasz np. 1 & 2→ 0, while 1 && 2→ true. Ponadto ^bitowe wyłączne lub, mogą działać nieprawidłowo w ten sposób. Uważane za wartości logiczne 1 i 2 są takie same, mianowicie true, ale traktowane jako wzorce bitów są różne.
Jak wyrazić logikę albo / lub w C ++.
Następnie podajesz trochę tła dla pytania,
„Czasami napotykam sytuacje, w których chcę, aby dokładnie jeden z dwóch warunków był prawdziwy (XOR), więc po prostu wrzucam operator ^ do wyrażenia warunkowego”.
Cóż, operatory bitowe mają wyższy priorytet niż operatory logiczne. Oznacza to w szczególności, że w wyrażeniu mieszanym, takim jak
a && b ^ c
otrzymujesz być może nieoczekiwany wynik a && (b ^ c).
Zamiast tego pisz po prostu
(a && b) != c
wyrażając bardziej zwięźle, co masz na myśli.
Dla wielu argumentów albo / albo nie ma operatora C ++, który wykonuje to zadanie. Na przykład, jeśli napiszesz a ^ b ^ c, to nie jest to wyrażenie, które mówi „albo a, balbo cjest prawdziwe”. Zamiast tego mówi, „nieparzysta liczba a, bi csą prawdziwe”, co może być 1 z nich lub wszystkich 3 ...
Aby wyrazić ogólne „albo / lub kiedy” a, bi csą typu bool, po prostu napisz
(a + b + c) == 1
lub, jeśli nie są boolargumentami, zamień je na bool:
(!!a + !!b + !!c) == 1
Używanie &=do gromadzenia wyników boolowskich.
Ty dalej rozwijasz,
„Ja też trzeba gromadzić wartości logiczne czasami, a &=i |=?mogą być bardzo użyteczne.”
Dobrze, odpowiada to sprawdzenie, czy odpowiednio wszystkie lub którykolwiek warunek jest spełniony, a de prawem Morgan mówi, jak przejść z jednego do drugiego. Oznacza to, że potrzebujesz tylko jednego z nich. Zasadniczo można by użyć *=jako &&=operatora (jak odkrył stary dobry George Boole, logiczne ORAZ można bardzo łatwo wyrazić jako mnożenie), ale myślę, że to zdziwiłoby i być może wprowadziłoby w błąd opiekunów kodu.
Weź również pod uwagę:
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;
}
Wyjście z Visual C ++ 11.0 i g ++ 4.7.1:
prawdziwe
fałszywy
Przyczyną różnicy w wynikach jest to, że poziom bitów &=nie zapewnia konwersji na boolargument po prawej stronie.
Które z tych wyników chcesz wykorzystać &=?
Jeśli to pierwsze, truelepiej zdefiniuj operator (np. Jak wyżej) lub nazwaną funkcję, albo użyj jawnej konwersji wyrażenia po prawej stronie, albo napisz aktualizację w całości.