Me encontré con el siguiente fragmento de código
if( 0 != ( x ^ 0x1 ) )
encode( x, m );
Que x ^ 0x1
significa ¿Es esta una técnica estándar?
c++
c
bit-manipulation
bitmask
KodeWarrior
fuente
fuente
0 != (x ^ 1)
→ xo ambos lados por 1 →(0 ^ 1) != (x ^ 1 ^ 1)
→ simplificar →1 != x
if (1 != x)
es difícil de escribir.type
delx
no se da - por lo tanto no sabemos que esto es un número entero en C ++ este problema etiquetado. Claro, si esto es C ox
es un número entero, la respuesta es fácil, pero eso no es un hecho yoperator ^
existe la posibilidad de sobrecarga .Respuestas:
La operación XOR (
x ^ 0x1
) invierte el bit 0. Por lo tanto, la expresión significa efectivamente: si el bit 0 de x es 0, o cualquier otro bit de x es 1, entonces la expresión es verdadera.Por el contrario, la expresión es falsa si x == 1.
Entonces la prueba es la misma que:
y por lo tanto (posiblemente) se ofusca innecesariamente.
fuente
^
es la operación XOR bit a bit0x1
está1
en notación hexadecimalx ^ 0x1
invertirá el último bit dex
(consulte la tabla de verdad XOR en el enlace de arriba si no está claro para usted).Entonces, la condición
(0 != ( x ^ 0x1 ))
será verdadera six
es mayor que 1 o si el último bit dex
es 0. Lo que solo deja x == 1 como un valor en el que la condición será falsa. Entonces es equivalente aPD: Una manera increíble de implementar una condición tan simple, podría agregar. No hagas eso. Y si debe escribir un código complicado, deje un comentario . Te lo ruego.
fuente
x==0
;4 ^ 0x1
es cierto, pero4==0
obviamente es falso.if (x == 0)
", ¿no es igual ax != 1
?x
es un tipo integral. Si es unfloat
odouble
, entonces creo que la expresión sería cierta para1.0 <= x < 2.0
. Y six
es un tipo definido por el usuario, la expresión podría ser verdadera si sex
trata de un Yugo, un canguro, el cumpleaños del famoso compositor o cualquier número que comparta al menos tres dígitos con el precio actual del té denominado en dólares en China.operator^
parafloat
/double
.Esto puede parecer una explicación demasiado simplificada, pero si a alguien le gustaría hacerlo lentamente, está debajo:
^
es un operador XOR bit a bit en c, c ++ y c #.La tabla de verdad de a xor b :
Así que vamos a ilustrar la
0 == ( x ^ 0x1 )
expresión a nivel binario:entonces:
fuente
Es operador exclusivo OR (XOR). Para entender cómo funciona, puede ejecutar este código simple
La salida será
Entonces esta expresión
será igual de verdadero solo cuando x! = 0x1.
No cambia x sí mismo. Solo comprueba si x es igual a 0 o 1. esta rxpression podría cambiarse a
fuente
Se comprueba que
x
en realidad no es0x1
...xor
INGx
con0x1
resultará en 0 sólo six
es0x1
... esto es un viejo truco utilizado sobre todo en lenguaje ensambladorfuente
!= 1
?xor
enfoque contenía menos código de máquina y se ejecutó más rápido que la asignación correspondiente a0
... sin embargo, esta pregunta contiene unxor
AND y una comparación, por lo que podría pensar que el!=
podría ser Más rápido. Sin embargo, no estoy tan seguro, necesitaría ver un ensamblado generado por el compilador.El
^
operador es bit a bit xor. Y0x1
es el número1
, escrito como una constante hexadecimal.Por lo tanto, se
x ^ 0x1
evalúa a un nuevo valor que es el mismo quex
, pero con el bit menos significativo invertido.El código no hace nada más que comparar x con 1, de una manera muy complicada y oscura.
fuente
El operador xor (exclusivo o) se usa más comúnmente para invertir uno o más bits. La operación es preguntar si exactamente uno de los bits es uno, esto lleva a la siguiente tabla de verdad (A y B son entradas, Y es salida):
Ahora, el propósito de este código parece ser verificar si excatly el último bit es 1, y los otros son 0, esto es igual
if ( x != 1 )
. La razón de este método oscuro podría ser que se han utilizado técnicas de manipulación de bits anteriores y tal vez se utilizan en otros lugares del programa.fuente
^
es bitxor operator
a bit adentroc
. En su caso, x es xor'ed con 1. por ejemplox
tiene el valor 10, entonces la10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d
condición se vuelve verdadera.fuente
10 != 1010
10 (decimal) == 1010 (binary)
b
o algo allí?La prueba bit a bit parece ser una ofuscación deliberada, pero si los datos subyacentes son datos corporativos de un sistema mainframe de IBM, puede ser simplemente que el código se escribió para reflejar la documentación original. Los formatos de datos de IBM se remontan a la década de 1960 y con frecuencia codifican banderas como bits individuales dentro de una palabra para ahorrar almacenamiento. A medida que se modificaron los formatos, se agregaron bytes de marca al final de los registros existentes para mantener la compatibilidad con versiones anteriores. La documentación para un registro SMF, por ejemplo, podría mostrar el código del lenguaje ensamblador para probar tres bits individuales dentro de tres palabras diferentes en un solo registro para decidir que los datos eran un archivo de entrada. Sé mucho menos sobre los componentes internos de TCP / IP, pero también puede encontrar indicadores de bits allí.
fuente
El operador ^ es bitwise-xor (ver &, |). El resultado para un par de bits es,
Entonces la expresión,
invierte / voltea el bit 0 de x (dejando otros bits sin cambios).
Considere si x puede tener valores además de 0x0 y 0x1? Cuando x es un campo de un solo bit, solo puede tener valores 0x0 y 0x1, pero cuando x es un int (char / short / long / etc), los bits además de bit0 pueden afectar el resultado de la expresión.
La expresión dada permite que los bits al lado de bit0 afecten el resultado,
Que tiene una veracidad equivalente a esta expresión (más simple),
Tenga en cuenta que esta expresión examinaría solo bit0,
Entonces, la expresión presentada realmente combina dos verificaciones de expresión,
¿El autor tenía la intención de verificar solo bit0, y tenía la intención de usar esta expresión,
¿O el autor tenía la intención de combinar los valores para bit1-bitN y el xor de bit0?
fuente
Estoy agregando una nueva respuesta porque nadie realmente explicó cómo obtener la respuesta intuitivamente.
El inverso de
+
es-
.El inverso de
^
es^
.¿Cómo resolver
0 != x - 1
parax
? Usted+ 1
a ambos lados:0 + 1 != x - 1 + 1
→1 != x
.¿Cómo resolver
0 != x ^ 1
parax
? Usted^ 1
a ambos lados:0 ^ 1 != x ^ 1 ^ 1
→1 != x
.fuente
Supongo que hay otros bits o valores de campo de bits
x
, y esto está destinado a probar que solo se establece el bit de orden inferior. En el contexto, supongo que este es el valor predeterminado y, por lo tanto, la codificación de esto y algunos relacionadosm
, por lo tanto, se puede omitir la (probablemente más caros de codificar), porque ambos deben ser el valor predeterminado, inicializados en un constructor o similar.De alguna manera, el decodificador debe poder inferir que faltan estos valores. Si están al final de alguna estructura, puede comunicarse a través de un
length
valor que siempre está presente.fuente
El XOR es útil en la enumeración de bandera de C #. Para eliminar un solo indicador del valor de enumeración, es necesario utilizar el operador xor (consulte aquí )
Ejemplo:
fuente
Hay muchas buenas respuestas, pero me gusta pensar de una manera más simple.
Ante todo. Una declaración if solo es falsa si el argumento es cero. Esto significa que comparar no igual a cero no tiene sentido.
Entonces eso nos deja con:
Un XOR con uno. Lo que hace un XOR es esencialmente detectar bits que son diferentes. Entonces, si todos los bits son iguales, devolverá 0. Dado que 0 es falso, la única vez que devolverá falso es si todos los bits son iguales. Por lo tanto, será falso si los argumentos son los mismos, verdadero si son diferentes ... al igual que el operador no igual a .
De hecho, la única diferencia entre los dos es que
!=
devolverá 0 o 1, mientras^
que devolverá cualquier número, pero la veracidad del resultado siempre será la misma. Una manera fácil de pensarlo es.La "simplificación" final es convertir
0x1
a decimal, que es 1. Por lo tanto, su declaración es equivalente a:fuente
^ es un operador XOR bit a bit
Si x = 1
aquí 0 == (x ^ 0x1)
Si x = 0
aquí 0! = (x ^ 0x1)
La tabla de verdad de a xor b:
El código simplemente significa
fuente
La técnica estándar que podría estar siendo utilizada, aquí, es repetir un modismo tal como aparece en el contexto circundante para mayor claridad, en lugar de ofuscarlo reemplazándolo por un modismo que es aritméticamente más simple pero contextualmente sin sentido.
El código circundante puede hacer referencia frecuente a
(x ^ 1)
, o la prueba puede estar preguntando "si el bit 0 fuera al revés, ¿esta máscara de bits estaría vacía?".Dado que la condición hace que algo sea
encode()
edite , puede ser que, en contexto, el estado predeterminado del bit 0 haya sido invertido por otros factores, y solo necesitamos codificar información adicional si alguno de los bits se desvía de su valor predeterminado (normalmente todo cero )Si toma la expresión fuera de contexto y pregunta qué hace, pasa por alto la intención subyacente. También podría mirar la salida del ensamblaje del compilador y ver que simplemente hace una comparación de igualdad directa con 1.
fuente
Como veo, las respuestas hasta ahora pierden una regla simple para manejar
XOR
s. Sin entrar en detalles sobre qué^
y qué0x
significan (yif
, y!=
etc.), la expresión0 != (x^1)
se puede reelaborar de la siguiente manera utilizando el hecho de que(a^a)==0
:fuente