2010-07-30 15 views
6

No entiendo la salida del siguiente programa:Explicar un conflicto aparente entre la precedencia de && y || y el resultado real de una expresión

#include<stdio.h> 

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 en lugar de -2 3 1 1, lo que implica que se evaluó ++i (e hizo que el operador de corto a || circule su lado derecho) antes de la expresión ++j && ++k que parece contradecir el hecho de que el operador && tiene una precedencia mayor que ||.

¿Alguien podría explicar por qué?

+1

¿Cuál es el tipo de m? –

+0

m es un número entero de tipo Sé que el anwer ... necesito explicación qué es k = 0 – anurag

+4

'' J' y K' Nunca se incrementa debido a que parte de la expresión está en cortocircuito. '++ i' es verdadero, por lo que el resto de la expresión no se evalúa. –

Respuesta

2

La expresión:

++i || ++j && ++k 

es equivalente a:

(++i) || ((++j) && (++k)) 

Explicando:

  1. ++i es evaluado - (-2) || ((++j) && (++k));
  2. El operador || se ha evaluado - (1);

Dado que 1 || anything evalúa verdadero, el operando correcto no se evalúa.Por lo tanto, la precedencia && no importa aquí. Este cortocircuito está garantizado tanto en C como en C++ por los estándares relevantes (ver Is short-circuiting logical operators mandated? And evaluation order?).

Ahora, trate de usar una sub-expresión, así:

(++i || ++j) && ++k 

que es equivalente a:

((++i) || (++j)) && (++k) 

Explicando:

  1. ++i es evaluado - ((-2) || (++j)) && (++k);
  2. || se evalúa - (1) && (++k)
  3. ++k se evalúa - (1) && (1);
  4. Evalúa verdadero;
3

-2 2 0 1

Lazy.

#include <stdio.h> 

int main() 
{ 

int i=-3,j=2,k=0; 
int m=++i||++j&&++k; 

printf("%d %d %d %d",i,j,k,m); 

} 

Compilar, ejecutar y ver por usted mismo.

gcc tmp.c -o tmp 
+0

Mis pensamientos exactamente – Tom

+1

¿No deberías && se ejecuta primero debido a una mayor precedencia? – anurag

+0

No. Esto está muy bien explicado en la respuesta de Jerry Coffin. El OP y otros simplemente tienen un problema de comprensión. –

22

La salida debe ser algo como:

Error, line 2: 'm': undefined variable. 

Editar: con el valor establecido, sólo el ++i deben ser evaluados. La precedencia no determina (ni afecta) el orden de evaluación. Precedencia significa que la expresión es equivalente a ++i || (++j && ++k). El orden de evaluación para || o && es siempre que se evalúa el operando izquierdo, luego 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, se evalúa el operando correcto de || si el operando izquierdo se evaluó a cero; el operando derecho de && se evalúa si se evaluó el operando izquierdo a no-cero).

En esta expresión, se evalúa ++i, porque es el operando izquierdo de || y se evalúa como distinto de cero, no se evalúa el resto de la expresión.

+1

+1 por hacerme reír. Estoy de acuerdo. : D –

+0

Originalmente era una línea, con la m formando parte de la declaración con el resto. Al dividirlo, el editor aparentemente dividió las líneas, insertando el error. –

+0

@James - Incluso cuando era un trazador de líneas había un ';' entre el k y el m. –

0

A modo de explicación:

#include <stdio.h> 

int main() 
{ 
    if (-1) 
     printf ("-1!\n"); 
    else 
     printf ("Not -1.\n"); 
    return 0; 
} 

Los números negativos no son falsas en C. Siempre comparar valores booleanos a 0 (o FALSE) o puede obtener mordido por if (worked == TRUE) dar falsos negativos.

Cuestiones relacionadas