c++ - sirve - sentencia if ejemplos
¿Por qué esta declaración if que combina una asignación y una verificación de igualdad devuelve verdadero? (4)
He estado pensando en algunos errores de principiantes y terminé con el de la declaración
if
.
Amplié un poco el código a esto:
int i = 0;
if (i = 1 && i == 0) {
std::cout << i;
}
He visto que la sentencia
if
devuelve verdadero, y
cout
''s
i
as
1
.
Si a
i
se le asigna
1
en la sentencia if, ¿por qué
i == 0
devolvió
true
?
Esto tiene que ver con la precedencia del operador .
if (i = 1 && i == 0)
no es
if ((i = 1) && (i == 0))
porque tanto
&&
y
==
tienen una prioridad más alta que
=
.
Lo que realmente funciona es
if (i = (1 && (i == 0)))
que asigna el resultado de
1 && (i == 0)
a
i
.
Entonces, si
i
comienza en
0
entonces
i == 0
es
true
, entonces
1 && true
es
true
(o
1
), y luego se establece en
1
.
Entonces, como
1
es verdadero, ingresa el bloque if e imprime el valor que asignó a
i
.
La respuesta real es:
- El compilador da prioridad a "i == 0", que se evalúa como verdadero.
- Luego evaluará i = 1 como VERDADERO o FALSO, y como los operadores de asignación compilados nunca fallan (de lo contrario no compilarían), también se evalúa como verdadero.
- Como ambas afirmaciones se evalúan como verdaderas, y TRUE && TRUE se evalúa como TRUE, la sentencia if se evaluará como TRUE.
Como prueba, solo mire la salida de asm de su compilador para el código que ingresó (todos los comentarios son míos):
mov dword ptr [rbp - 8], 0 ; i = 0;
cmp dword ptr [rbp - 8], 0 ; i == 0?
sete al ; TRUE (=1)
mov cl, al
and cl, 1 ; = operator always TRUE
movzx edx, cl
mov dword ptr [rbp - 8], edx ; set i=TRUE;
test al, 1 ; al never changed,
; so final ans is TRUE
La salida de asm anterior fue de CLANG, pero todos los demás compiladores que miré dieron una salida similar.
Tenga en cuenta que su compilador no estableció realmente i = 1, pero i = TRUE. Esto se debe a que el operador && solo evalúa si una declaración es VERDADERA o FALSA, y luego establece los resultados de acuerdo con ese resultado. Como prueba, intente cambiar i = 1 a i = 2 y puede observar que nada cambiará. Compruébelo usted mismo utilizando cualquier compilador en línea en Compiler Explorer
Suponiendo que su código realmente se ve así:
#include <iostream>
using namespace std;
int main() {
int i = 0;
if (i = 1 && i == 0) {
cout << i;
}
}
Luego esto:
if (i = 1 && i == 0) {
evalúa como
if (i = (1 && i == 0)) {
y así
i
pongo a
1
.
Tiene que ver con analizar las reglas de derecha a izquierda.
Ej. Y = x + 5.
Todas las sub-expresiones son ponderadas en importancia.
Dos expresiones de igual importancia se evalúan de derecha a izquierda,.
El lado de && expresión se hace primero, seguido por el LHS.
Tiene sentido para mi.