programacion - Comportamiento de && en lenguaje de programación C
operadores logicos en lenguaje c (5)
Debido a la evaluación de cortocircuito , cuando x
es 0
, y
z
no necesitan ser evaluados ya que 0 && ANYTHING
es 0
.
Una vez que x
se incrementa a 0
, el resultado es 0
, y eso es lo que obtiene y
.
z
permanece sin cambios ( -1
).
x | y | z
----+----+-----
-1 | -1 | -1 //x = y = z = -1;
0 | -1 | -1 //++x && ... Now the whole expression is evaluated to 0
0 | 0 | -1 //y = ++x && ++y && ++z;
Soy un principiante en lenguaje de programación C, recientemente he leído acerca de Logical AND &&
operator.
También sé que, en el lenguaje de programación C, todos los valores distintos de cero se tratan como VERDADERO .
NON-ZERO && NON-ZERO = 1
NON-ZERO && ZERO = 0
ZERO && NON-ZERO = 0
ZERO && ZERO = 0
Pero cuando estoy tratando con el siguiente programa, entonces no recibo la respuesta esperada.
int main(){
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, x, y, z);
return 0;
}
Estoy esperando
x = 0, y = 0, z = 0
pero la respuesta es
x = 0, y = 0, z = -1
¿Alguien puede explicar, por qué recibo esta respuesta?
Edit: En esta pregunta, no he preguntado sobre la precedencia de los operadores.
Lo que sucede es que ++y
y ++z
nunca se evalúan porque la primera parte ya garantiza cuál será el nuevo valor de y
.
La primera parte de su declaración es ++x && ...
que es equivalente a 0 && ...
y ya sabemos que y
será 0 al final, por lo que el resto de la declaración no se ejecuta.
si hiciste esto
int main(){
int x,y,z,tmp;
x = y = z = -1;
tmp = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, tmp = %d", x,y,z, tmp);
return 0;
}
Obtendría x = 0, y = -1, z = -1, tmp = 0
La evaluación de la izquierda está garantizada en el estándar C99. Puede encontrarlo en la sección 6.5.13 Logical AND operator
A diferencia del operador y binario bitwise, el operador && garantiza la evaluación de izquierda a derecha; hay un punto de secuencia después de la evaluación del primer operando. Si el primer operando se compara igual a 0, el segundo operando no se evalúa.
Puede encontrar más información sobre lo que es un punto de secuencia en Wikipedia o en el Anexo C de la norma C99
Solo puedo pensar en que &&
evalúa en corto circuito : dado A && B
, si A
evalúa false
entonces B
no es evaluado.
Asi que:
X
convierte en 0
. && ++y && ++z
no evalúa desde X/0/false && ...
y=0
asignado de y = x/0/false
z
permanece sin modificar ya que ++z
no se ejecuta.
&&
operador de &&
se evalúa por pares, por lo que supongo que C está evaluando
((++x && ++y) && ++z)
ahora, ++x
devolverá cero, por lo tanto, el primer &&
fallará, al igual que el segundo sin la necesidad de evaluar ++y
o ++z
.
y = 0
ya que es el resultado de la expresión.
z
no se toca
Para completar (volcado de cerebro):
El término detrás de esta brujería se llama cortocircuito . Revisemos tu código y luego una breve reseña sobre por qué sucede esto. Mirando a:
int main( void ) {
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf( "x = %d, y = %d, z = %d, x, y, z );
return 0;
}
... comenzamos a dividirla línea por línea. La primera línea:
int x, y, z;
... declara tres enteros, x
, y
y z
. Se inicializan en valores de basura en el marco de pila porque no hay inicialización (operador de asignación). Esta línea realmente no importa, ahora veamos la siguiente:
x = y = z = -1;
... vemos que estamos haciendo múltiples tareas en la misma línea. Recuerde que el operador de asignación mutará el identificador a la izquierda del operador de asignación (utilizando el valor a la derecha del operador de asignación) y devolverá el valor de x
. Esto se conoce como sobrecarga de asignación. Pero, de nuevo, esto no importa en realidad, lo único importante que debemos tener en cuenta es que x
, y
, z
, ahora son todos -1. Veamos la siguiente línea:
y = ++x && ++y && ++z;
... dice la brujería Yoda. Agreguemos el paréntesis para que sea más obvio qué paso se evalúa primero:
y = ( ( ++x ) && ++y && ++z );
... ahora, mirando el paréntesis más interno, vemos que es un incremento de prefijo de x
, lo que significa que incrementaremos el valor de x
y luego lo devolveremos. Notamos que x
es originalmente -1 y ahora es 0 después de ser incrementado. Esto se resolverá de la siguiente manera:
y = ( 0 && ++y && ++z );
... ahora es importante notar que mirando nuestras tablas de verdad:
A | B | A && B
--------------
T | T | T
T | F | F
F | T | F
F | F | F
... para el operador lógico AND
vemos que tanto F (AND) T, T (AND) F son F. El compilador se da cuenta de esto y se cortocircuita cuando está evaluando una conjunción (AND) donde un valor es false
- Una técnica inteligente de optimización. Entonces se resolverá asignando y
para ser 0 (que es falso). Recuerde que en C cualquier valor distinto de cero es true
, solo 0 es false
. La línea se verá como sigue:
y = 0;
... ahora mirando la siguiente línea:
printf( "x = %d, y = %d, z = %d, x, y, z );
... debería ser obvio ahora que generará x = 0, y = 0, z = -1
.