No entiendo la salida del siguiente progtwig:
#include int main() { int i=-3, j=2, k=0, m; m = ++i || ++j && ++k; printf("%d %d %d %d\n", i, j, k, m); return 0; }
La salida es -2 2 0 1
lugar de -2 3 1 1
, lo que implica que ++i
se evaluó (y provocó que el operador ||
cortocircuitara su lado derecho) antes de la expresión ++j && ++k
que parece contradecir el hecho de que el operador &&
tiene mayor prioridad que ||
.
¿Alguien explicaría por qué?
La expresion:
++i || ++j && ++k
Es equivalente a:
(++i) || ((++j) && (++k))
Explicando
++i
se evalúa – (-2) || ((++j) && (++k))
(-2) || ((++j) && (++k))
; ||
el operador es evaluado – (1)
; Desde 1 || anything
Todo 1 || anything
evalúa es verdadero, el operando correcto no es evaluado. Por lo tanto, la precedencia de &&
no importa aquí. Este cortocircuito está garantizado tanto en C como en C ++ por los estándares relevantes (ver ¿Se obligan los operadores lógicos de cortocircuito? ¿Y el orden de evaluación? ).
Ahora, intenta usar una sub-expresión, como esta:
(++i || ++j) && ++k
Lo que equivale a:
((++i) || (++j)) && (++k)
Explicando
++i
se evalúa – ((-2) || (++j)) && (++k)
; ||
se evalúa – (1) && (++k)
++k
se evalúa – (1) && (1)
; La salida debe ser algo como:
Error, line 2: 'm': undefined variable.
Edición: con eso arreglado, solo el ++i
debería ser evaluado. La precedencia no determina (ni siquiera afecta) el orden de evaluación. Precedencia significa que la expresión es equivalente a ++i || (++j && ++k)
++i || (++j && ++k)
. Orden de evaluación para ||
o &&
siempre es que se evalúa el operando izquierdo, entonces hay un punto de secuencia. Después del punto de secuencia, el operando derecho se evalúa si y solo si es necesario para determinar el resultado final (es decir, el operando derecho de ||
se evalúa si el operando izquierdo se evalúa a cero; el operando derecho de &&
se evalúa si el operando izquierdo evaluado a no cero).
En esta expresión, ++i
se evalúa, entonces porque es el operando izquierdo de ||
y evaluado no cero, no se evalúa nada del rest de la expresión.
-2 2 0 1
Perezoso.
#include int main() { int i=-3,j=2,k=0; int m=++i||++j&&++k; printf("%d %d %d %d",i,j,k,m); }
Comstackr, correr y ver por ti mismo.
gcc tmp.c -o tmp
A modo de explicación:
#include int main() { if (-1) printf ("-1!\n"); else printf ("Not -1.\n"); return 0; }
Los números negativos no son falsos en C. Siempre compare los valores booleanos con 0 (o FALSE
) o puede ser mordido por if (worked == TRUE)
dando falsos negativos.