Desventajas de los operadores de nivel de bits.
Usted pregunta:
“¿Hay alguna razón para no usar los operadores de bits &
, |
y ^
para los 'valores BOOL' en C ++? "
Sí, los operadores lógicos , que es la incorporada en operadores booleanos de alto nivel !
, &&
y ||
, ofrecer las siguientes ventajas:
Garantizada conversión de argumentos a bool
, es decir, a 0
y 1
valor ordinal.
Evaluación de cortocircuito garantizada donde la evaluación de expresión se detiene tan pronto como se conoce el resultado final.
Esto se puede interpretar como una lógica de valor de árbol, con Verdadero , Falso e Indeterminado .
Equivalentes textuales legibles not
, and
e or
incluso si no los uso yo mismo.
Como lector de antimonio notas en un comentario también a los operadores bitlevel tienen fichas alternativas, a saber bitand
, bitor
,xor
y compl
, pero en mi opinión estos son menos legible que and
, or
y not
.
En pocas palabras, cada una de estas ventajas de los operadores de alto nivel es una desventaja de los operadores de nivel de bits.
En particular, dado que los operadores bit a bit carecen de conversión de argumentos a 0/1, se obtiene, por ejemplo , 1 & 2
→ 0
, mientras que 1 && 2
→ true
. Además ^
, bit a bit exclusivo o, puede comportarse mal de esta manera. Considerados como valores booleanos 1 y 2 son iguales, es decir true
, pero considerados como patrones de bits, son diferentes.
Cómo expresar una lógica o una en C ++.
A continuación, proporcione algunos antecedentes para la pregunta,
"A veces me encuentro con situaciones en las que quiero que se cumpla exactamente una de las dos condiciones (XOR), por lo que simplemente lanzo el operador ^ a una expresión condicional".
Bueno, los operadores bit a bit tienen mayor precedencia que los operadores lógicos. Esto significa, en particular, que en una expresión mixta como
a && b ^ c
obtienes el resultado quizás inesperado a && (b ^ c)
.
En su lugar, escribe solo
(a && b) != c
expresando de forma más concisa lo que quieres decir.
Para el argumento múltiple o / o no hay operador de C ++ que hace el trabajo. Por ejemplo, si se escribe a ^ b ^ c
de lo que no es una expresión que dice “ya sea a
, b
o c
es verdad”. En su lugar, dice, “un número impar de a
, b
yc
son verdaderos”, que podría ser 1 de ellos o los 3 ...
Para expresar el general o cuando a
, b
y c
son de tipo bool
, simplemente escriba
(a + b + c) == 1
o, sin bool
argumentos, conviértalos a bool
:
(!!a + !!b + !!c) == 1
Utilizando &=
para acumular resultados booleanos.
Usted elabora más,
"También necesito acumular valores booleanos a veces, &=
y |=?
puede ser bastante útil".
Bueno, esto corresponde a comprobar si se cumple respectivamente todas o alguna de las condiciones, y la ley de De Morgan te dice cómo pasar de una a otra. Es decir, solo necesitas uno de ellos. En principio, podría utilizarlo *=
como&&=
operador (porque, como descubrió el bueno de George Boole, el Y lógico se puede expresar fácilmente como una multiplicación), pero creo que eso dejaría perplejos y quizás engañaría a los mantenedores del código.
Considere también:
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;
}
Salida con Visual C ++ 11.0 y g ++ 4.7.1:
cierto
falso
La razón de la diferencia en los resultados es que el nivel de bits &=
no proporciona una conversión a bool
su argumento del lado derecho.
Entonces, ¿cuál de estos resultados desea utilizar &=
?
Si es el primero, true
entonces defina mejor un operador (por ejemplo, como arriba) o una función nombrada, o use una conversión explícita de la expresión del lado derecho, o escriba la actualización completa.