bitwise - if or c
¿Por qué es "if(i++ &&(i== 1))" falso donde i es un int que contiene el valor 1? (5)
{
int i = 1;
if (i++ && (i == 1))
printf("Yes/n");
else
printf("No/n");
}
Según mi entendimiento, en la condición if
, primero se evaluará la expresión ( i==1
) que debería devolver 1
, y luego se andedó lógicamente con 1
que es el valor de i
, por lo que la expresión debería devolver 1 && 1 == 1
, pero la parte else
se ejecuta.
¿Puede alguien explicar por qué se ejecuta la parte else
?
Creo que 1 && 1 = 1 y 1 && 0 = 0 es claro para ti. La respuesta de Michael L me parece bien. Pero todavía intentaré elaborar un poco. Aquí hay un enlace que proporciona la lista de precedencia del operador:
http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
Si visita este enlace y consulta esa tabla, sabrá que && tiene asociatividad de izquierda a derecha. Por lo tanto, primero me convertiré en 2 DESPUÉS de la parte izquierda (Sruit intentó mostrar este diagrama de uso); luego, en la parte derecha i == 1 verificación está hecha. Podemos verificar esto escribiendo el código como el que se muestra a continuación:
Este código explica que i = 2 cuando el flujo de ejecución alcanza i == 1 parte.
#include <stdio.h>
int main() {
int i = 1;
if (i++ && (printf("%d/n",i)))
printf("Yes/n");
else
printf("No/n");
return 0;
}
Entonces la salida es:
2
Sí
¡Entonces 2 == 1 resulta ser falso y finalmente la respuesta da una sensación sorprendente! El soporte del lado derecho da 0 y el lado izquierdo 1, así 1 && 0 = 0. Creo que esto es justo para entender.
Cuando &&
se usa en una expresión, se garantiza que sus argumentos se evaluarán de izquierda a derecha . Entonces tendré el valor de 2
cuando se evalúa (i==1)
. Por lo tanto, la expresión es falsa y la parte else
se ejecutará.
Sin embargo, tenga en cuenta que si el argumento de la izquierda se evalúa como falso o 0, entonces el argumento de la derecha no se evalúa en absoluto.
Está confundido porque en el enunciado de bucle, i ++ se usa para el incremento posterior. p.ej
for (i=0;i<1;i++)
En el programa de bucle anterior, primero obtendré un valor inicial y verificaré la condición. La condición if
es verdadera, por lo que aumenta i y evalúa i a un valor anterior para el cuerpo del bucle, pero fuera del cuerpo del bucle tiene un nuevo valor 1 .
En su pregunta está usando if
y el alcance del valor antiguo de i
finalizará cuando se encuentre lógicamente. El operador automáticamente obtendrá un nuevo valor e incrementará a 2 por lo que la condición devuelve falso.
No. En C, hay un punto de secuencia entre la evaluación del LHS del operador &&
y la evaluación del RHS, y el incremento debe realizarse y completarse antes de que se evalúe el RHS. Entonces, el i++
(equivalente a i++ != 0
) se ejecuta y el incremento se completa (y la expresión se evalúa como verdadera), de modo que cuando se evalúa el RHS, i == 2
y por lo tanto, la expresión general es falsa y usted obtener ''No'' impreso. Si el LHS del operador &&
evaluado a falso (0), el RHS no se evaluaría debido a la propiedad de ''cortocircuito'' del operador &&
.
Solo unos pocos operadores tienen la propiedad de tener un punto de secuencia entre la evaluación de LHS y RHS: &&
, ||
y ,
(como operador, no como separador en una lista de argumentos) - ¿y hay ? :
? :
también, que no es un operador binario pero que tiene un punto de secuencia después de evaluar la condición y antes de la expresión después de ?
o la expresión después de :
se evalúa (de los cuales uno u otro, pero no ambos, siempre se evalúa).
El &&
y ||
los operadores son los únicos operadores con la propiedad de ''cortocircuito''. El RHS de &&
solo se evalúa si el LHS se evalúa como verdadero; el RHS de ||
solo se evalúa si el LHS lo evalúa como falso.
Aclaración de puntos de secuencia
Iwillnotexist Idonotexist asserted correctamente:
El estándar C11 no ha eliminado los puntos de secuencia, solo lo hizo el estándar C ++ 11.
C ++ 11 (ISO / IEC 14882: 2011) dice:
1.9 Ejecución del programa
¶13 Secuenciado anteriormente es una relación asimétrica, transitiva, por pares, entre evaluaciones ejecutadas por un único hilo (1.10), que induce un orden parcial entre esas evaluaciones. Dadas dos evaluaciones A y B , si A se secuencia antes de B , entonces la ejecución de A precederá a la ejecución de B. Si A no está secuenciado antes de que B y B no estén secuenciados antes de A , entonces A y B no son secuenciados . [ Nota: la ejecución de evaluaciones no secuenciadas puede superponerse. - nota final ] Las evaluaciones A y B se secuencian indefinidamente cuando A se secuencia antes de que B o B se secuencian antes que A , pero no se especifica qué. [ Nota: las evaluaciones secuenciadas indefinidamente no pueden superponerse, pero cualquiera podría ejecutarse primero. - nota final ]
El término ''punto de secuencia'' no aparece en absoluto en C ++ 11 (la única coincidencia cercana es ''puntero de secuencia'').
C11 (ISO / IEC 9899: 2011) dice:
5.1.2.3 Ejecución del programa
¶3 Secuenciado anteriormente es una relación asimétrica, transitiva y por pares entre evaluaciones ejecutadas por un único hilo, lo que induce un orden parcial entre esas evaluaciones. Dadas dos evaluaciones A y B , si A se secuencia antes de B , entonces la ejecución de A precederá a la ejecución de B. (Por el contrario, si A se secuencia antes de B , entonces B se secuencia después de A ). Si A no se secuencia antes o después de B , entonces A y B no son secuenciados . Las evaluaciones A y B se secuencian indefinidamente cuando A se secuencia antes o después de B , pero no se especifica qué. 13) La presencia de un punto de secuencia entre la evaluación de las expresiones A y B implica que cada cálculo de valor y efecto secundario asociado con A se secuencia antes de cada cálculo de valor y efecto secundario asociado con B. (Un resumen de los puntos de secuencia se da en el anexo C.)
13) Las ejecuciones de evaluaciones no secuenciadas pueden intercalarse. Las evaluaciones secuenciadas indefinidamente no pueden intercalarse, pero se pueden ejecutar en cualquier orden.
Entonces, C11 retiene los puntos de secuencia, pero agrega los términos ''secuenciada antes'' y los términos relacionados usando esencialmente la misma terminología que C ++ 11.
Aquí, una explicación simple
y es por eso que esta condición se convierte en "falsa"