Pregunta

& amp; tiene & amp; & amp; . | tiene || . ¿Por qué ^ no tiene ^^ ?

Entiendo que no sería un cortocircuito, pero tendría una semántica diferente. En C, true es realmente cualquier valor distinto de cero. Bitwise XOR no siempre es lo mismo que el XOR lógico:

int a=strcmp(str1,str2);// evaluates to 1, which is "true"
int b=strcmp(str1,str3);// evaluates to 2, which is also "true"
int c=a ^^ b; // this would be false, since true ^ true = false
int d=a ^ b; //oops, this is true again, it is 3 (^ is bitwise)

Dado que no siempre puede confiar en que un valor verdadero sea 1 o -1 , un operador ^^ no sería muy ¿servicial? A menudo tengo que hacer cosas extrañas como esta:

if(!!a ^ !!b) // looks strange
¿Fue útil?

Solución

Dennis Ritchie responde

  

Hay razones tanto históricas como prácticas por las que no existe un operador ^^ .

     

La práctica es: no hay mucho uso para el operador. El punto principal de & amp; & amp; y || es aprovechar su evaluación de cortocircuito no solo por razones de eficiencia, sino más a menudo por expresividad y corrección. < br>   [...]
  Por el contrario, un operador ^^ siempre forzaría la evaluación de ambos brazos de la expresión, por lo que no hay ganancia de eficiencia. Además, las situaciones en las que realmente se requiere ^^ son bastante raras, aunque se pueden crear ejemplos. Estas situaciones se vuelven más raras y extrañas a medida que apilas al operador--

if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...
     

hace el consecuente exactamente cuando un número impar de condx () s es verdadero. Por el contrario, los análogos & amp; & amp; y || siguen siendo bastante plausibles y útiles.

Otros consejos

Técnicamente, ya existe uno:

a != b

ya que esto se evaluará como verdadero si el valor de verdad de los operandos difiere.

Editar:

Comentario de

Volte :

(!a) != (!b)

es correcto porque mi respuesta anterior no funciona para los tipos int . Eliminaré la mía si agrega su respuesta.

Editar de nuevo:

Quizás esté olvidando algo de C ++, pero cuanto más pienso en esto, más me pregunto por qué escribirías if (1 ^ 2) en primer lugar. El propósito de ^ es excluir uno o dos números juntos (que se evalúa a otro número), no convertirlos en valores booleanos y comparar sus valores de verdad.

Esto parece una suposición extraña para un diseñador de idiomas.

Para operandos que no son bool , supongo que lo que desearía es que a ^^ b se evalúe como:

(a != 0) ^ (b != 0)

Bueno, tiene la opción anterior y tiene algunas opciones enumeradas en otras respuestas.

El operador ^^ sería redundante para los operandos bool . Hablando solo de operandos booleanos, en aras de la discusión, supongamos que ^ era solo bit a bit y que ^^ existía como un XOR lógico. Entonces tiene estas opciones:

  • & amp; - Bitwise AND - siempre evalúa ambos operandos
  • & amp; & amp; - AND lógico - no siempre evalúa ambos operandos
  • | - Bitwise OR - siempre evalúa ambos operandos
  • || - OR lógico - no siempre evalúa ambos operandos
  • ^ - Bitwise XOR - siempre debe evaluar ambos operandos
  • ^^ - XOR lógico - siempre debe evaluar ambos operandos

¿Por qué no crearon ^^ para convertir esencialmente valores numéricos en bool sy luego actuar como ^ ? Buena pregunta. Quizás porque es más potencialmente confuso que & amp; & amp; y || , quizás porque puede construir fácilmente el equivalente de ^^ con otros operadores .

No puedo decir qué había en las cabezas de Kernighan y Ritchie cuando inventaron C, pero hiciste una breve referencia a "no sería un cortocircuito", y supongo que esa es la razón: es No es posible implementarlo consistentemente. No se puede hacer un cortocircuito en XOR como se puede hacer AND y OR, por lo que ^^ no podría estar completamente en paralelo & amp; & amp; y ||. Por lo tanto, los autores bien podrían haber decidido que hacer una operación que parezca paralela a las demás, pero que no lo sea, sería peor que no tenerla en absoluto.

Personalmente, la razón principal por la que uso & amp; & amp; y || es para el cortocircuito en lugar del no bit a bit. En realidad, rara vez uso los operadores bit a bit.

Otra solución alternativa a las publicadas anteriormente (incluso si requiere otra rama en el código) sería:

if ( (a? !b : b ) )

que es equivalente a xor.

En Java, el operador ^ realmente hace XOR lógico cuando se usa en dos operandos booleanos (al igual que & amp; y | en Java do AND y OR lógicos sin cortocircuito, respectivamente, cuando se aplican a booleanos). La principal diferencia con C / C ++ es que C / C ++ le permite mezclar enteros y booleanos, mientras que Java no lo hace.

Pero creo que es una mala práctica usar enteros como booleanos de todos modos. Si desea realizar operaciones lógicas, debe atenerse a los valores bool o a los enteros que son 0 o 1. Luego, ^ funciona bien como XOR lógico.

Una pregunta análoga sería preguntar, ¿cómo haría AND y OR lógico sin cortocircuito en C / C ++? La respuesta habitual es utilizar los operadores & amp; y | respectivamente. Pero, de nuevo, esto depende de que los valores sean bool o 0 o 1. Si permite valores enteros, entonces esto tampoco funciona.

Independientemente del caso a favor o en contra de ^^ como operador, por ejemplo con strcmp () es una mierda. No devuelve un valor de verdad (verdadero o falso), devuelve una relación entre sus entradas, codificada como un entero.

Claro, cualquier número entero puede interpretarse como un valor de verdad en C, en cuyo caso 0 es "falso" y todos los demás valores son "verdaderos", pero eso es lo contrario de lo que strcmp () devuelve.

Su ejemplo debería comenzar:

int a = strcmp(str1, str2) == 0; // evaluates to 0, which is "false"
int b = strcmp(str1, str3) == 0; // evaluates to 0, which is also "false"

Debe comparar el valor de retorno con 0 para convertirlo en un valor booleano adecuado que indique si las cadenas son iguales o no.

Con "apropiado" booleanos, representados canónicamente como 0 o 1, el operador ^ a nivel de bits también funciona mucho mejor ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top