2010-07-19 31 views
8

Duplicar posible:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)de incremento posterior del operador: Comportamiento inesperado

Mi código es el siguiente:

#include <stdio.h> 
int main() 
{ 
    int x = 10, y = 0; 
    x = x++; 
    printf("x: %d\n", x); 
    y = x++; 
    printf("y: %d\n", y); 
} 

dada la naturaleza de post-incremento, lo esperaría la siguiente salida:

x: 10 
y: 10 

Mi razonamiento es que en la línea 5, x debe asignarse a su valor inicial después de que el incremento tenga lugar.

En su lugar, sin embargo, me sale esto:

x: 11 
y: 11 

de excavación en el conjunto, esto parece una elección deliberada para mí:

LCFI2: 
     movl $10, -4(%rbp) // this is x 
     movl $0, -8(%rbp) // this is y 
     incl -4(%rbp)  // x is simply incremented 
     movl -4(%rbp), %esi 
     leaq LC0(%rip), %rdi 
     movl $0, %eax 
     call _printf 
     movl -4(%rbp), %eax // now x is saved in a register, 
     movl %eax, -8(%rbp) // copied to y, 
     incl -4(%rbp)  // and finally incremented 
     movl -8(%rbp), %esi 
     leaq LC1(%rip), %rdi 
     movl $0, %eax 
     call _printf 

lo que está pasando aquí? ¿GCC está tratando de salvarme de mí mismo? No tengo una referencia de lenguaje a mano, pero hubiera pensado que esto rompe la semántica deseada.

+0

abominaciones !!! –

+0

http://en.wikipedia.org/wiki/Sequence_point – Ken

+0

En los malos viejos tiempos, 'a = 1 + a' en ciertos idiomas era una mina en la que todos los nuevos errores se ponían a prueba. –

Respuesta

13

El comportamiento no está definido ya que no hay un punto de secuencia intermedio en x = x++, consulte p. Ej. el C FAQ.

+0

¡Gracias! No era consciente previamente de los puntos de secuencia. – danben

4

El lenguaje C lo deja indefinido en cuanto a cuándo se produce exactamente una publicación/preincidencia/decremento. Por lo tanto, declaraciones como x = x++ no están bien formadas; evítelas.

+1

Más precisamente, no está permitido modificar una variable más de una vez en una expresión. 6.5/2: * "Entre el punto de secuencia anterior y el siguiente, un objeto tendrá su valor almacenado modificado como máximo una vez por la evaluación de una expresión." * – sth

+2

@sth: Más precisamente, "más de uno entre los puntos de secuencia". Es posible que una expresión contenga un punto de secuencia, en cuyo caso la modificación de una variable más de una vez está bien. Por ejemplo, '&&', '||' y el operador de coma pueden todos formar puntos de secuencia dentro de una sola expresión. –

+0

@sth: Incluso _más precisamente_, eso no es una limitación en el codificador, es una limitación de la variable en sí misma. Su afirmación de que "no está permitido ..." no es del todo correcto. Está permitido, es una tontería :-) – paxdiablo

1

Cuando se tiene:

a = b++; 

lo que está sucediendo es que b se guarda en una y después de la assigment se hace b se incrementa en uno. Así que si lo hace:

x = x ++; 

y anteriormente x fue de 10 lo que sucederá es 10 se guardarán en x y después (antes de printf se hace) x se incrementa en uno a 11. Es por eso que 11 se imprime.

2

Normas aparte (ya que esto no está definido con respecto al estándar), la forma en que se ejecutó es la que yo esperaba.

Mi regla de oro es que para una línea con x++, sustituyes x++ con x y poner x += 1 en la siguiente línea (o la línea anterior para pre-incremento).

Siguiendo esa regla de tres, el código debería escribirse como

#include <stdio.h> 
int main() 
{ 
    int x = 10, y = 0; 
    x = x; // x: 10 
    x += 1; // x: 11 
    printf("x: %d\n", x); 
    y = x; // y: 11 
    x += 1; // x: 12 
    printf("y: %d\n", y); 
} 
Cuestiones relacionadas