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 0
i 1
wartoś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
, and
a or
nawet 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
, xor
i compl
, ale moim zdaniem są mniej czytelne niż and
, or
i 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
, b
albo c
jest prawdziwe”. Zamiast tego mówi, „nieparzysta liczba a
, b
i c
są prawdziwe”, co może być 1 z nich lub wszystkich 3 ...
Aby wyrazić ogólne „albo / lub kiedy” a
, b
i c
są typu bool
, po prostu napisz
(a + b + c) == 1
lub, jeśli nie są bool
argumentami, 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 bool
argument po prawej stronie.
Które z tych wyników chcesz wykorzystać &=
?
Jeśli to pierwsze, true
lepiej 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.