Operadores lógicos

Los operadores "&&", "||" y "!" relacionan expresiones lógicas, dando como salida a su vez nuevas expresiones lógicas. Sintaxis:

<expresión1> && <expresión2>
<expresión1> || <expresión2>
!<expresión>

El operador "&&" equivale al "AND" o "Y"; devuelve true sólo si los dos operandos true o lo que es equivalente, distintas de cero. En cualquier otro caso el resultado es false.

El operador "||" equivale al "OR" u "O inclusivo"; devuelve true si cualquiera de las expresiones evaluadas es true, o distinta de cero, en caso contrario devuelve false.

El operador "!" es equivalente al "NOT", o "NO", y devuelve true cuando la expresión evaluada es false o cero, en caso contrario devuelve false.

Cortocircuito

Existe una regla que en muchas ocasiones nos puede resultar útil, ya que nos puede ahorrar tiempo y comprobaciones adicionales.

Esta regla se conoce como "cortocircuito" o "shortcut", y se aplica de forma diferente a expresiones AND y OR.

En el caso de operaciones AND, consiste en que si la primera expresión evaluada es false, la segunda si siquiera se evalúa, ya que el resultado será siempre false independientemente del valor del segundo operando.

En el caso de operaciones OR, si la primera expresión sea true, la segunda no se evalúa, ya que el resultado será siempre true, independientemente del valor de la segunda expresión.

Esto es porque en una operación && el resultado sólo puede ser true cuando los dos operandos sean true, y en una operación || el resultado sólo puede ser false si ambos operandos son false. En el momento en que en una expresión AND uno de los operandos sea false, o que en una expresión OR uno de los operandos sea true, el valor del otro operando es irrelevante.

Si tenemos en cuenta este comportamiento, podremos ahorrar tiempo de ejecución si colocamos en primer lugar la expresión más fácil de calcular, o aquella cuyo valor sea más probablemente false en el caso de una expresión AND o true, para una expresión OR.

También habrá casos en que una de las expresiones sea indeterminada cuando la otra sea false en una expresión AND, o true en una expresión OR. En ese caso, será preferible colocar la expresión potencialmente indeterminada en el segundo lugar.

Tablas de verdad

Una tabla de verdad es una relación de todos los posibles valores para los operandos que intervienen en una operación, y los resultados para cada caso.

En el caso de operadores lógicos podemos mostrar fácilmente tablas de verdad, ya que el dominio para cada operando es muy reducido: true o false. Si además tenemos en cuenta la regla del cortocircuito, los casos posibles se reducen todavía más.

A continuación se muestra la tabla de verdad del operador &&:

Expresión1 Expresión2 Expresión1 && Expresión2
false ignorada false
true false false
true true true

La tabla de verdad para el operador || es:

Expresión1 Expresión2 Expresión1 || Expresión2
false false false
false true true
true ignorada true

La tabla de verdad para el operador ! es:

Expresión !Expresión
false true
true false

Expresiones lógicas frecuentes

A menudo aprovechamos ciertas equivalencias entre enteros y valores lógicos para comprobar algunos valores especiales en comparaciones usadas en condiciones o bucles.

Concretamente, me refiero a las comparaciones con cero. Así, si queremos saber si un valor entero E, es distinto de cero, lo comparamos usando el operador !=: 0!=E.

Pero existe una correspondencia entre todos los valores enteros y los valores booleanos, y esa correspondencia es muy simple: un valor entero nulo esquivale a false, cualquier valor entero distinto de cero, equivale a true.

Teniendo esto en cuenta, la comparación anterior es inncecesaria, ya que 0!=E es equivalente a usar, sencillamente E.

La condición contraria, 0==E, es por lo tanto equivalente a lo contrario, es decir, a la expresión !E.

Será pues, muy frecuente, que encuentres este tipo de operadores lógicos aplicados a enteros en condiciones:

if(!E) {...} // Si E es cero, hacer ...
if(E) {...} // Si E no es cero, hacer...

Operador "sizeof"

Este operador tiene dos usos diferentes.

Sintaxis:

sizeof (<expresión>)
sizeof (nombre_de_tipo)

En ambos casos el resultado es una constante entera que da el tamaño en bytes del espacio de memoria usada por el operando, que es determinado por su tipo. El espacio reservado por cada tipo depende de la plataforma.

En el primer caso, el tipo del operando es determinado sin evaluar la expresión, y por lo tanto sin efectos secundarios. Si el operando es de tipo char, el resultado es 1.

A pesar de su apariencia, sizeof() NO es una función, sino un OPERADOR.

Asociación de operadores binarios

Cuando decimos que un operador es binario no quiere decir que sólo se pueda usar con dos operandos, sino que afecta a dos operandos. Por ejemplo, la línea:

A = 1 + 2 + 3 - 4;

Es perfectamente legal, pero la operación se evaluará tomando los operandos dos a dos y empezando por la izquierda, y el resultado será 2. Además hay que mencionar el hecho de que los operadores tienen diferentes pesos, es decir, se aplican unos antes que otros, al igual que hacemos nosotros, por ejemplo:

A = 4 + 4 / 4;

Dará como resultado 5 y no 2, ya que la operación de división tiene prioridad sobre la suma. Esta propiedad de los operadores es conocida como precedencia. En el capítulo de operadores II se verán las precedencias de cada operador, y cómo se aplican y se eluden estas precedencias.

Del mismo modo, el operador de asignación también se puede asociar:

A = B = C = D = 0;

Este tipo de expresiones es muy frecuente en C++ para asignar el mismo valor a varias variables, en este caso, todas las variables: A, B, C y D recibirán el valor 0.

Generalización de cortocircuitos

Generalizando, con expresiones AND con más de dos operandos, la primera expresión false interrumpe el proceso e impide que se continúe la evaluación del resto de las operaciones.

De forma análoga, con expresiones OR con más de dos operandos, la primera expresión true interrumpe el proceso e impide que se continúe la evaluación del resto de las operaciones.

Palabras reservadas usadas en este capítulo

sizeof.

Comentarios de los usuarios (13)

Raul
2011-01-08 06:39:48

El curso me parece excelente. Solamente quisiera hacer un comentario en cuanto a lo que has decidido llamarle "cortocircuito". La palabra "shortcut" se traduce como atajo (o en terminos informaticos como acceso directo) y me parece que realmente las tablas de verdad que muestras son exactamente eso: una forma mas rapida (atajo) de llegar al punto deseado. Una vez mas, felicitaciones por el curso y gracias.

Salvador Pozo
2011-01-10 14:25:46

Primero, gracias por tu comentario.

En cuanto al concepto de "cortocircuito", estoy de acuerdo contigo y posiblemente "atajo" es una traducción más exacta, pero aprovecho para hacer un par de comentarios.

- En la mayoría de la documentación sobre C y C++ que puedas encontrar en español verás que se usa la expresión "evaluación en cortocircuito" para este mecanismo. Sólo sigo la tradición :).

- En realidad, incluso cuando se habla de circuitos eléctricos, un cortocircuito es un atajo. La corriente no sigue el circuito prefijado, sino que usa un circuito más corto, en la mayoría de los casos con efectos indeseados. Podríamos decir que "cortocircuito" también es un sinónimo de atajo, y una traducción posible de "shortcut".

Steven
2011-01-20 16:22:23

Hola Raúl y Salvador,

Tienes razón que la traducción de "shortcut" es "atajo". Sin embargo, el término inglés que se usa para definir el concepto de saltarse la evaluación de subcondiciones que forman parte de una condición - más compleja - por el motivo de que lógicamente no es necesaria se llama "shortcircuit". La traducción correcta de "shortcircuit" es "cortocircuito".

Steven

valdive
2012-01-24 16:06:41

Es mas un "atajo" que un corto circuito, porque el primero tiene un resultado deseable, pues no sigue evaluando cuando ya a obtenido un resultado. Yo he hecho muchos corto circuitos con resultados desastrosos. De todas maneras el programa pretende conseguir el resultado con el menor exfuerzo posible y en el menor tiempo.

Calculin
2012-04-08 23:33:16

El cortocircuito es util tambien cuando la no existencia de una condicion pudiera provocar un error en las siguientes evaluaciones, por lo que es imprescindible que no siga evaluando.

Excelente curso.

Adri
2014-12-20 21:50:38

Informacion extra:

-La operacion logica XOR corresponde a este simbolo: ^

-Si en lugar de usar los simbolos && || ! ^

escribimos and or not xor respectivamente, tambien es valido

-Si en lugar de escribir && escribimos &, tambien es valido,

pero es recomendable usar && para evitar confusion, porque

como ya se vera mas adelante, & sirve tambien para indicar

la dirrecion donde esta guardada una variable

Adri
2014-12-24 01:32:39

Otra cosa mas:

-Si escribimos not en lugar de ! tambien es valido.

Steven R. Davidson
2014-12-31 17:22:49

Hola Adri,

Unas cuantas aclaraciones:

- En C/C++, no existe un operador para la operación lógica de XOR (OR eXclusivo). El símbolo ^ representa la operación XOR a nivel de bits.

- Existen vocablos para representar algunos operadores.

- Existe una gran diferencia entre el operador && (AND lógico) y el operador & (AND a nivel de bits). Puede haber casos en los que el comportamiento es el mismo con un operador u otro, pero en general no son intercambiables. Lo mismo sucede con los operadores || (OR lógico) y | (OR a nivel de bits); y los operadores ! (NOT lógico) y ~ (NOT a nivel de bits o complemento).

Tienes razón que el símbolo & también puede servir para representar la operación de obtener la dirección de memoria de una variable, pero es unitario a diferencia de la operación AND, que es binaria. Más adelante, también veremos que el mismo símbolo sirve como declarador para crear referencias.

Espero haber aclarado las dudas.

Steven

Adrian
2016-09-25 02:10:30

En este enlace queda mas claro el asunto de las palabras reservadas que funcionan como operadores lógicos:

https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#C.2B.2B%5Foperator%5Fsynonyms

En cualquier caso, el operador logico XOR es en esencia lo mismo que "!=", ya que p xor q es verdadero cuando p y q son diferentes (p verdadero y q falso, o p falso y q verdadero)

Adrian
2016-09-25 02:14:09

Los cortocircuitos no suelen tenerse mucho en cuenta, pero junto a las funciones es algo importante, ya que si yo tengo algo como:

if(b && f()) cout << "a" << endl;

Y la f() ademas de devolver un booleano modifica algunas variables globales o atributos de la clase en la que se haya creado, entonces puede ser un verdadero quebradero de cabeza descubrir que algun error puede deberse a que f() no siempre se ejecuta y dichas variables no modifican su valor por el cortocircuito.

Mapaor
2017-06-24 18:39:18

A ver, porfavor alguien me puede explicar lo del operador sizeof, no he entendido ni una palabra de lo que hay explicado. Espero que este no sea el punto donde tienes que dejarlo porque ya no entiendes lo que te explican.

Steven R. Davidson
2017-06-25 02:24:31

Hola Mapaor,

El operador 'sizeof' sirve para conseguir la cantidad de bytes que ocupa un tipo de dato. Por ejemplo,

sizeof(int)

bajo un compilador particular, puede resultar en el valor 4; es decir, 'int' ocuparía 4 bytes. Pero, bajo otro compilador, es posible que el resultado sea 2 bytes o incluso 8 bytes.

Aparte de usar un tipo de dato, también se permite escribir una expresión como operando. Por ejemplo,

sizeof (4+6*2/3.0)

seguramente daría el resultado de 8 (bytes), ya que si se evaluase esta expresión el tipo de dato resultante sería 'double' que suele ocupar 8 bytes. Por otro lado, si tenemos el siguiente ejemplo muy similar,

sizeof (4+6*2/3)

lo más seguro es que el resultado sería de 4 (bytes), ya que su evaluación resultaría en un valor de tipo 'int', que suele ocupar 4 bytes.

Por ahora no te preocupes mucho por este operador, ya que se usa en ciertos momentos propicios y en la práctica, diríamos que son técnicas algo más avanzadas.

Espero haber aclarado la duda.

Steven

Mapaor
2017-06-26 10:58:39

Muchas gracias Steven, ahora entiendo más o menos lo que es, gracias por la respuesta i por dedicarle tanto a este curso