¿Por qué '&&' y no '&'?


135

¿Por qué es &&preferible &y ||preferible |?

Le pregunté a alguien que ha estado programando durante años y su explicación fue:

Por ejemplo, in if (bool1 && bool2 && bool3) { /*DoSomething*/ }, bool1tiene que ser verdadero para que pruebe bool2cuál tiene que ser verdadero antes de continuar bool3, etc. Si hubiera usado uno solo, &no hay ningún orden para la prueba, incluso si todos tienen que ser fieles a avanzar a la siguiente línea, entonces, ¿por qué importa de todos modos?

Nota: Me gustaría señalar que soy el equivalente de programación de un niño pequeño y esta no es una pregunta seria o urgente. Es más una cuestión de entender por qué las cosas deben hacerse de cierta manera en lugar de otra.


55
& y && | y || son operadores completamente diferentes
Felice Pollano

3
Reetiquetado, ya que esto no solo se aplica a C #
Jonathan Dickinson

12
Revertido, porque las respuestas ya son específicas de C # y el funcionamiento interno puede diferir un poco en otros lenguajes que generalmente tienen el mismo concepto.
Daniel Hilgarth

8
@Felice: Son diferentes, pero apenas completamente diferentes. De hecho, son muy similares: x & yy x && ysiempre evaluarán el mismo resultado si x e y son expresiones de tipo booleano. De hecho, la única diferencia en ese caso parece ser que en x & yy siempre se evalúa.
Joren

1
@slawekin: Sugeriría leer las respuestas. Algunos escriben extensamente sobre las diferencias de rendimiento. Sin embargo, la respuesta podría sorprenderte.
Abel

Respuestas:


183

En la mayoría de los casos, &&y ||se prefiere sobre &y |porque el primero se cortocircuitan-, lo que significa que la evaluación se cancela en cuanto el resultado es claro.

Ejemplo:

if(CanExecute() && CanSave())
{
}

Si CanExecutedevuelve false, la expresión completa será false, independientemente del valor de retorno de CanSave. Debido a esto, CanSaveno se ejecuta.

Esto es muy útil en las siguientes circunstancias:

string value;
if(dict.TryGetValue(key, out value) && value.Contains("test"))
{
    // Do Something
}

TryGetValuedevuelve falsesi la clave suministrada no se encuentra en el diccionario. Debido a la naturaleza de cortocircuito de &&, value.Contains("test")solo se ejecuta cuando TryGetValueregresa truey, por lo tanto, valueno null. Si utilizara el operador AND bit a bit en su& lugar, obtendría un NullReferenceExceptionsi la clave no se encuentra en el diccionario, porque la segunda parte de la expresión se ejecuta en cualquier caso.

Un ejemplo similar pero más simple de esto es el siguiente código (como lo menciona TJHeuvel):

if(op != null && op.CanExecute())
{
    // Do Something
}

CanExecutesolo se ejecuta si opno es así null. Si opes así null, la primera parte de la expresión ( op != null) se evalúa falsey op.CanExecute()se omite la evaluación del resto ( ).

Aparte de esto, técnicamente, son diferentes, también:
&&y ||sólo se puede utilizar en la boolque, &y |se puede utilizar en cualquier tipo integral ( bool, int, long, sbyte, ...), porque son operadores bit a bit. &es el operador AND a nivel de bit y |es el operador OR a nivel de bit .

Para ser muy exactos, en C #, esos operadores ( &, |[y ^]) se denominan "operadores lógicos" (consulte la especificación de C # , capítulo 7.11). Hay varias implementaciones de estos operadores:

  1. Para enteros ( int, uint, longy ulong, capítulo 7.11.1):
    Se llevan a cabo para calcular el resultado bit a bit de los operandos y el operador, es decir, &es implementar para calcular la lógica bit a bit ANDetc.
  2. Para enumeraciones (capítulo 7.11.2):
    Se implementan para realizar la operación lógica del tipo subyacente de la enumeración.
  3. Para bools y booleos anulables (cap. 7.11.3 y 7.11.4):
    El resultado no se calcula utilizando cálculos bit a bit. El resultado se busca básicamente en función de los valores de los dos operandos, porque el número de posibilidades es muy pequeño.
    Debido a que ambos valores se usan para la búsqueda, esta implementación no está en cortocircuito.

31
Esto también puede ser útil para verificar si algo es nulo. Por ejemplo: if(op != null && op.CanExecute()). Debido a que la segunda causa no se evalúa cuando la primera no es verdadera, esto es válido.
TJHeuvel

2
@TJHeuvel: Este es básicamente el mismo uso que describí con mi TryGetValueejemplo. Pero sí, es otro buen ejemplo de esto.
Daniel Hilgarth

44
Buena respuesta. Quizás también debería agregar un ejemplo de cómo &o |se usa con argumentos no bool (es decir, lo que hacen los operadores) en beneficio de todas las personas nuevas.
Zabba

81

Explicar muy claramente lo que esto significa (aunque las otras respuestas lo insinúen, pero probablemente usen terminología que no entiendes).

El siguiente código:

if (a && b)
{
   Foo();
}

Realmente está compilado para esto:

if (a)
{
    if (b)
    {
        Foo();
    }
}

Donde el siguiente código se compila exactamente como se representa:

if (a & b)
{
   Foo();
}

Esto se llama cortocircuito. En general, siempre debe usar &&y ||en sus condiciones.

Marcas de bonificación: hay un escenario en el que no deberías. Si se encuentra en una situación en la que el rendimiento es crucial (y esto es crucial en nanosegundos ), solo use el cortocircuito cuando sea necesario (por ejemplo, la nullcomprobación), ya que un cortocircuito es una bifurcación / salto; lo que podría dar lugar a una predicción errónea de rama en su CPU; una &es mucho más barato que &&. También hay un escenario en el que los cortocircuitos en realidad pueden romper la lógica: eche un vistazo a esta respuesta mía.

Diatribe / Monologue : con respecto a la predicción errónea de la rama que ignoramos con la mayor felicidad. Citando a Andy Firth (quien ha estado trabajando en juegos durante 13 años): "Este puede ser un nivel más bajo que la gente piensa que necesitan ir ... pero estarían equivocados. Comprender cómo el hardware que está programando para las ramas de golosinas puede afectar el rendimiento a un GRAN grado ... mucho más de lo que la mayoría de los programadores pueden apreciar re: muerte por mil cortes ".

  • Los desarrolladores de juegos (y otros que trabajan en condiciones extremas en tiempo real) llegan a reestructurar su lógica para adaptarse mejor al predictor. También hay evidencia de esto en el código mscorlib descompilado.
  • El hecho de que .NET te proteja de este tipo de cosas no significa que no sea importante. Una predicción errónea de rama es terriblemente costosa a 60 Hz; o a 10,000 solicitudes / segundo.
  • Intel no tendría herramientas para identificar la ubicación de las predicciones erróneas, ni Windows tendría un contador de rendimiento para esto, ni habría una palabra para describirlo, si no fuera un problema.
  • La ignorancia sobre los niveles más bajos y la arquitectura no hace que alguien que los conoce esté equivocado.
  • Siempre trate de comprender las limitaciones del hardware en el que está trabajando.

Aquí hay un punto de referencia para los no creyentes. Es mejor ejecutar el proceso en tiempo real / alto para mitigar el planificador que tiene un efecto: https://gist.github.com/1200737


77
Sobre las "marcas de bonificación": Todos sabemos lo bueno que resulta de la optimización prematura. :)
un CVn

66
@Michael: por eso 'nano-segundos crucial' está en negrita :). Los desarrolladores de juegos AAA generalmente se preocupan por cosas como esta, y nunca se sabe quién leerá las respuestas; así que siempre es mejor documentar incluso los casos límite / extremos.
Jonathan Dickinson

1
¿Es esa marca de bonificación válida para C #? Pensé que no, como se interpreta MSIL, a menos que la expresión se compile hasta el código de la máquina.
Jeremy McGee

77
@Jeremy MSIL no se interpreta.
Jonathan Dickinson

2
@TheD vuelva a verificar la respuesta: he agregado un monólogo sobre por qué DEBERÍA preocuparse por esto. Y, para su información, se (x && y)traduce a LOAD x; BRANCH_FALSE; LOAD y; BRANCH_FALSE;donde se (x & y)traduce LOAD x; LOAD y; AND; BRANCH_FALSE;. Una rama versus dos.
Jonathan Dickinson

68

Operador lógico ( ||y &&) vs. operador bit a bit ( |y &).

La diferencia más crucial entre un operador lógico y un operador bit a bit es que un operador lógico toma dos booleanos y produce un booleano, mientras que un operador bit a bit toma dos enteros y produce un entero (nota: enteros significa cualquier tipo de datos integral, no solo int).

Para ser pedante, un operador bit a bit toma un patrón de bits (por ejemplo, 01101011) y realiza un AND / OR en cada bit. Entonces, por ejemplo, si tiene dos enteros de 8 bits:

a     = 00110010 (in decimal:    32+16+2   = 50)
b     = 01010011 (in decimal: 64+   16+2+1 = 83)
----------------
a & b = 00010010 (in decimal:       16+2   = 18)
a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)

mientras que un operador lógico solo funciona en bool:

a      = true
b      = false
--------------
a && b = false
a || b = true

En segundo lugar, a menudo es posible usar un operador bit a bit en bool ya que verdadero y falso es equivalente a 1 y 0 respectivamente, y sucede que si traduce verdadero a 1 y falso a 0, entonces realiza una operación a nivel de bit, luego convierte un valor distinto de cero a verdadero y cero a falso; sucede que el resultado será el mismo si hubiera utilizado el operador lógico (verifique esto para hacer ejercicio).

Otra distinción importante es también que un operador lógico está en cortocircuito . Por lo tanto, en algunos círculos [1], a menudo se ve gente haciendo algo como esto:

if (person && person.punch()) {
    person.doVictoryDance()
}

que se traduce como: "si la persona existe (es decir, no es nula), intente golpearla, y si el golpe tiene éxito (es decir, vuelve verdadero), entonces haga un baile de victoria" .

Si hubiera utilizado un operador bit a bit en su lugar, esto:

if (person & person.punch()) {
    person.doVictoryDance()
}

se traducirá a: "si la persona existe (es decir, no es nula) y el golpe tiene éxito (es decir, vuelve verdadero), entonces haga un baile de victoria" .

Tenga en cuenta que en el operador lógico en cortocircuito, el person.punch()código puede no ejecutarse si persones nulo. De hecho, en este caso particular, el segundo código produciría un error de referencia nulo si persones nulo, ya que intenta llamar person.punch()sin importar si la persona es nula o no. Este comportamiento de no evaluar el operando correcto se llama cortocircuito .

[1] Algunos programadores criticarán por poner una llamada de función que tenga un efecto secundario dentro de una ifexpresión, mientras que para otros es un idioma común y muy útil.

Dado que un operador bit a bit trabaja en 32 bits a la vez (si está en una máquina de 32 bits), puede generar un código más elegante y rápido si necesita comparar una gran cantidad de condiciones, por ejemplo

int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3,
    CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6;

Person person;
person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS;

Place bar;
bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK;

Place military;
military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT;

CurrentLocation cloc1, cloc2;
cloc1.usable_abilities = person_abilities & bar_rules;
cloc2.usable_abilities = person_abilities & military_rules;

// cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT`
// while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`

Hacer lo mismo con operadores lógicos requeriría una cantidad incómoda de comparaciones:

Person person;
person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true;
person.can_shoot_cannons = false;

Place bar;
bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true;
bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false;

Place military;
military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true;
military.rules.can_drink = military.rules.can_talk = false;

CurrentLocation cloc1;
bool cloc1.usable_abilities.can_punch         = bar.rules.can_punch         && person.can_punch,
     cloc1.usable_abilities.can_kick          = bar.rules.can_kick          && person.can_kick,
     cloc1.usable_abilities.can_drink         = bar.rules.can_drink         && person.can_drink,
     cloc1.usable_abilities.can_sit           = bar.rules.can_sit           && person.can_sit,
     cloc1.usable_abilities.can_shoot_guns    = bar.rules.can_shoot_guns    && person.can_shoot_guns,
     cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons
     cloc1.usable_abilities.can_talk          = bar.rules.can_talk          && person.can_talk;

bool cloc2.usable_abilities.can_punch         = military.rules.can_punch         && person.can_punch,
     cloc2.usable_abilities.can_kick          = military.rules.can_kick          && person.can_kick,
     cloc2.usable_abilities.can_drink         = military.rules.can_drink         && person.can_drink,
     cloc2.usable_abilities.can_sit           = military.rules.can_sit           && person.can_sit,
     cloc2.usable_abilities.can_shoot_guns    = military.rules.can_shoot_guns    && person.can_shoot_guns,
     cloc2.usable_abilities.can_talk          = military.rules.can_talk          && person.can_talk,
     cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;

Un ejemplo clásico donde se usan patrones de bits y operadores bit a bit es en los permisos del sistema de archivos Unix / Linux.


3
+1 para el lado afecta el problema. Sorprendido de que no se mencionó antes
Conrad Frix

3
el ejemplo parece un poco violento, pero parece que otras respuestas se centraron demasiado en cortocircuitos y no lo suficiente en la diferencia entre operar con enteros y booleanos.
R0MANARMY

La función debe entenderse antes de que entren en juego los detalles de implementación (cortocircuito / efectos secundarios). Me alegro de que haya aclarado la diferencia principal: lógica booleana frente a lógica entera, no cortocircuito.
Abel

@ROMANARMY - violento, me encanta la ironía dada a tu monje. Buen trabajo
brumScouse

8

En el caso de:

if (obj != null && obj.Property == true) { }

funcionaría como se esperaba.

Pero:

if (obj != null & obj.Property == true) { }

potencialmente podría lanzar una excepción de referencia nula.


2

Corto y simple:

1 && 2= verdadero
porque
1 = verdadero (no cero) en C
2 = verdadero (no cero) en C

trueANDS lógicamente con truedar true.

Pero

1 & 2= 0 = falso
porque
1 = 0001 en binario
2 = 0010 en binario

0001 ANDs a nivel de bit con 0010 para dar 0000 = 0 en decimal.

Del mismo modo para || y | operadores también ...!


2
-1: Estamos hablando de C # aquí ... 1 && 2es ilegal en C #
Daniel Hilgarth

Pero este es un ejemplo extremadamente importante que explica por qué no puedes simplemente intercambiar & y && (que muchas personas parecen pensar).
bobobobo

1

&&es la versión de corto circuito de &.

Si estamos evaluando false & true, ya sabemos al observar el primer argumento que el resultado será falso. La &&versión del operador devolverá un resultado tan pronto como sea posible, en lugar de evaluar la expresión completa. También hay una versión alemana similar del |operador, ||.


1
if (list.Count() > 14 && list[14] == "foo")

es seguro

if (list.Count() > 14 & list[14] == "foo")

se bloquearía si la lista no tiene el tamaño correcto.


No puedo imaginar que alguien pueda escribir "if (list.Count ()> 14 & list [14] ==" foo ")" en lugar de "if (list.Count ()> 14 && list [14] ==" foo ")". & simplemente y naturalmente no se puede usar para && en este caso, incluso si 's es seguro (lista [1] por ejemplo).
Tien Do

1

Los operadores de C # deben explicar por qué:

Esencialmente tener dos &'s o |' s significa que es condicional más que lógico, por lo que puede notar la diferencia entre los dos.

& Operator tiene un ejemplo de uso de uno&.


Ambos enlaces están (efectivamente) rotos (redirige a "Documentación retirada de Visual Studio 2005" ).
Peter Mortensen

1

OK, en valor nominal

    Boolean a = true;
    Boolean b = false;

    Console.WriteLine("a({0}) && b({1}) =  {2}", a, b, a && b);
    Console.WriteLine("a({0}) || b({1}) =  {2}", a, b, a || b);
    Console.WriteLine("a({0}) == b({1}) =  {2}", a, b, a == b);

    Console.WriteLine("a({0}) & b({1}) =  {2}", a, b, a & b);
    Console.WriteLine("a({0}) | b({1}) =  {2}", a, b, a | b);
    Console.WriteLine("a({0}) = b({1}) =  {2}", a, b, a = b);

Producir la misma respuesta. Sin embargo, como mostró, si tiene una pregunta más compleja, entonces:

if (a and b and c and d) ..

Si ano es cierto y tal vez bes una función en la que tiene que apagarse, conectarse a algo, obtener esto, hacer eso, tomar una decisión ... ¿por qué molestarse? Pérdida de tiempo, ya sabes que ya ha fallado. ¿Por qué hacer que la máquina se apague y haga un trabajo extra sin sentido?

Siempre lo he usado &&porque pongo los más propensos a fallar primero, ergo, menos cálculos antes de continuar cuando no tiene sentido. Si no hay forma de predecir opciones menos probables, como si tiene un valor booleano para limitar la salida de datos, algo como:

if (limit && !MyDictionary.ContainsKey("name")) 
    continue;

Si no es así limit, no se moleste en buscar la clave, lo que podría llevar más tiempo.


1

Cuando se usa en una expresión lógica como una declaración if &&preferible porque dejará de evaluar expresiones tan pronto como se encuentre el primer resultado falso. Esto es posible porque un valor falso hará que toda la expresión sea falsa. De manera similar (y nuevamente en expresiones lógicas) ||es preferible porque dejará de evaluar expresiones tan pronto como encuentre una expresión verdadera porque cualquier valor verdadero hará que toda la expresión sea verdadera.

Sin embargo, si las expresiones de ser o de opinión o e-ed juntos tienen efectos secundarios, y desea que todo esto suceda como resultado de su expresión (sin importar el resultado de la expresión lógica), a continuación, &y |podría ser utilizado. Por el contrario, los operadores &&y ||pueden ser útiles como protección contra los efectos secundarios no deseados (como un puntero nulo que provoca una excepción).

Los operadores &y |también se pueden usar con enteros y, en este caso, producen un resultado entero que son los dos operandos y-ed o-ed juntos en el nivel de bit. Esto puede ser útil cuando los bits binarios de un valor entero se usan como una matriz de valores verdaderos y falsos. Para probar si un cierto bit está activado o desactivado, una máscara de bits se asigna a los bits y se edita con el valor. Para activar un bit, la misma máscara puede ser ordenada bit a bit con el valor. Finalmente, para desactivar un poco, el complemento a nivel de bit (usando ~) de una máscara es bit a bit con el valor.

int a = 0; // 0 means all bits off
a = a | 4; // set a to binary 100
if ((a & 4) != 0) {
    // will do something
}
a = a & (~4) // turn bit off again, a is now 000

En lenguajes distintos de C #, se debe tener cuidado con los modos lógico versus bit a bit de & y |. En el código anterior, la ifexpresión condicional de la declaración (a & 4) != 0es una forma segura de expresar esta condición, pero en muchos lenguajes similares a C, las declaraciones condicionales pueden simplemente tratar los valores enteros cero como valores enteros falsos y no cero como verdaderos. (La razón de esto se relaciona con las instrucciones de procesador de ramificación condicional disponibles y su relación con el indicador de cero que se actualiza después de cada operación de entero.) Por lo tanto ìf, la prueba de cero de la instrucción puede eliminarse y la condición podría acortarse (a & 4).

Esto podría causar confusión e incluso problemas cuando las expresiones se combinen usando los valores de retorno bit a bit y del operador que no tienen bits que se alinean. Considere el siguiente ejemplo donde se desean los efectos secundarios de dos funciones, antes de verificar que ambos tuvieron éxito (según lo definido por ellos devolviendo un valor distinto de cero):

if (foo() & bar()) {
    // do something
}

En C, si foo()devuelve 1 y bar()devuelve 2, el "algo" no se hará porque 1 & 2es cero.

C # requiere declaraciones condicionales como iftener un orandrand booleano, y el lenguaje no permite que un valor entero se convierta en un valor booleano. Entonces el código anterior generaría errores de compilación. Se expresaría más correctamente de la siguiente manera:

if (foo() != 0 & bar() != 0) {
    // do something
}

1

Si eres un antiguo programador de C, ten cuidado . C # realmente me ha sorprendido.

MSDN dice para el |operador:

Binario | Los operadores están predefinidos para los tipos integrales y bool . Para tipos integrales, | calcula el OR bit a bit de sus operandos. Para los operandos bool, | calcula el OR lógico de sus operandos; es decir, el resultado es falso si y solo si sus dos operandos son falsos.

(El énfasis es mío.) Los tipos booleanos se manejan especialmente, y en este contexto la pregunta solo comienza a tener sentido, y la diferencia es que, como otros ya se han expandido en sus respuestas:

&&y ||están en corto circuito. &y |evaluar ambos operandos.

y lo que es preferible depende de muchas cosas como los efectos secundarios, el rendimiento y la legibilidad del código, pero en general, los operadores de cortocircuito son preferibles también porque son mejor comprendidos por personas con antecedentes similares como yo.

La razón es: diría un argumento como este: dado que no hay un tipo booleano real en C, podría usar el operador bit a bit |y hacer que su resultado sea evaluado como verdadero o falso en una condición if. Pero esta es la actitud incorrecta para C #, porque ya existe un caso especial para los tipos booleanos.


0

Es importante, porque si el costo de evaluación de bool2 (por ejemplo) es alto pero bool1 es falso, entonces se ha ahorrado un poco de cómputo utilizando && over &


0

Porque &&y ||se utilizan para el control de flujo tal como if/elseson. No siempre se trata de condicionales. Es perfectamente razonable escribir como una declaración, no como ifo whilecondicional, lo siguiente:

 a() && b() && c() && d();

o incluso

 w() || x() || y() || z();

No es solo que sean más fáciles de escribir que las if/elseversiones equivalentes ; También son mucho más fáciles de leer y entender.


0

&& y & significan dos cosas muy diferentes y le dan dos respuestas diferentes.

1 && 2produce 1 ("verdadero")
1 & 2produce 0 ("falso")

&&es un operador lógico; significa "verdadero si ambos operandos son verdaderos"
&es una comparación bit a bit. Significa "dime cuáles de los bits están configurados en ambos operandos"


2
La pregunta es sobre C #. En C #, no hay forma de emitir un número a un bool, por lo que 0 no es 'falso' y no es cero 'verdadero'; simplemente no hay equivalencia.
Nate CK

Para convertir el número a bool, de manera que 1 significa verdadero y 0 significa falso, diga "n! = 0" (supongo ... no estoy realmente familiarizado con C #). En realidad, quería retractar este comentario ya que no está bien investigado y no creo que sea útil o realmente relevante para el comentario anterior ahora que lo pienso más, pero accidentalmente presioné enter y ahora no creo que pueda cancélelo, así que aquí tiene, para lo que sea que valga :-)
Don Hatch

1 && 2da un error de compilación: "Error 4 Operador '&&' no se puede aplicar a operandos de tipo 'int' e 'int'"
Peter Mortensen

0

La forma más rápida (y un poco tonta) de explicar esto a las personas que NO NECESITAN conocer las operaciones exactas del código cuando se hace esto

&& está haciendo una verificación de cada una de esas condiciones hasta que encuentre un falso y devuelva todo el resultado como falso

|| está haciendo una verificación de cada una de esas condiciones hasta que encuentra un verdadero y devuelve todo el resultado como verdadero.

& está haciendo MATHS basado en AMBAS / TODAS las condiciones y lidiando con el resultado.

El | está haciendo MATHS basado en AMBAS / TODAS las condiciones y lidiando con el resultado.

Nunca me he encontrado con un punto en el que haya necesitado usar & o | dentro de una declaración if. Principalmente lo uso para cortar valores hexadecimales en los colores de sus componentes usando el desplazamiento bit a bit.

P.EJ:

r = fullvalue >> 0xFF & 0xFF;
g = fullvalue >> 0xF & 0xFF;
b = fullvalue & 0xFF;

Dentro de esta operación "& 0xFF" está obligando a mirar solo el valor binario. No he encontrado personalmente un uso para |sin embargo.


0

Simplemente,

if exp1 && exp2

si exp1 es flase no marque exp2

pero

if exp1 & exp2

si exp1 es falseO true verifique exp2

y rara vez las personas usan &porque rara vez quieren verificar exp2 si exp1 esfalse

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.