2010-09-01 14 views
12

Estoy usando Coverity Prevent en un proyecto para encontrar errores."x = ++ x" ¿es realmente indefinido?

Se informa de un error para esta expresión (Los nombres de las variables son, por supuesto cambiado):

x= 
    (a>= b) ? 
    ++x: 0; 

El mensaje es: defecto

EVALUATION_ORDER: En "x=(a>= b) ? ++x: 0;", "x" es escrito en "x" (la asignación LHS) y escrito en "(a>= b) ? ++x: 0;", pero el orden en que se producen los efectos secundarios no está definido porque no hay punto de secuencia intermedio. FIN DEL MENSAJE

Si bien puedo entender que "x = x++" no está definido, este es un poco más difícil para mí. ¿Es este un falso positivo o no?

+1

El título de tu pregunta es confuso. Usted dice que entiende que 'x = x ++' no está definido. Sin embargo, el título de su pregunta parece preguntar si 'x = ++ x' está definido. ¿Eso significa que no entiendes que 'x = ++ x' no está definido? ¿O su pregunta es realmente sobre el caso con el operador '?:' Condicional? – AnT

+0

Perdón por la confusión. Entendí que x = x ++ no está definido, pero no (tiempo pasado) entendí por qué (y si) x = ++ x no estaba definido. ¿No creí eso?: Era la principal putrefacción del problema, por lo tanto lo omití (desafortunadamente sin decir por qué). Pero para preservar la integridad del mensaje de Coverity, lo mantuve en el mensaje de Coverity. Estoy de acuerdo en que eso hizo mi pregunta un poco confusa. –

+0

¿Esto también está indefinido para JAVA? Porque veo aquí http://www.careercup.com/question?id=13543663 y la versión más votada sugiere que dará un resultado definido. – user007

Respuesta

28

operador condicional ?: tiene un punto de secuencia entre la evaluación de la condición (primer operando) y la evaluación de segundo o tercer operando, pero no tiene ningún punto de secuencia dedicado después de la evaluación de segundo o tercer operando. Lo que significa que dos modificaciones de x en este ejemplo son potencialmente conflictivas (no separadas por un punto de secuencia). Entonces, Coverity Prevent tiene razón.

Su declaración en ese sentido es prácticamente equivalente a

a >= b ? x = ++x : x = 0; 

con el mismo problema que en x = ++x.

Ahora, el título de su pregunta parece sugerir que no sabe si x = ++x no está definido. De hecho, no está definido. No está definido por el mismo motivo x = x++ no está definido. En resumen, si el mismo objeto se modifica más de una vez entre un par de puntos de secuencia adyacentes, el comportamiento no está definido. En este caso, x se modifica por asignación y por ++ y no hay punto de secuencia para "aislar" estas modificaciones entre sí. Entonces, el comportamiento no está definido. No hay absolutamente ninguna diferencia entre ++x y x++ en este sentido.

+0

+1: Estoy sorprendido de por qué Comeau Online no da error en este caso o en el caso simple de 'x = x ++;' – Chubsdad

+0

@chubsdad: No recuerdo que Comeau Online haya detectado situaciones similares. Se sabe que GCC publica advertencias en casos como ese, pero no se queja del caso '?:'. – AnT

+0

¿Esto también está indefinido para JAVA? Porque veo aquí http://www.careercup.com/question?id=13543663 y la versión más votada sugiere que dará un resultado definido. – user007

12

Independientemente de la precisión del mensaje, al reemplazar el código en cuestión por x= (a>= b) ? x+1: 0; se logra el mismo fin sin confusión. Si la herramienta está confundida, tal vez la siguiente persona que vea este código también lo haga.

Esto supone que x no tiene un operador de incremento sobrecargado con efectos secundarios de los que depende aquí.

+0

Y, por la bondad de tu corazón a otros desarrolladores, no llames a 'x',' a' y 'b'. –

+0

@Dominic: la pregunta establece claramente que los nombres cambiaron de los nombres originales. –

+0

@Joachim - ah, lo perdí, ¡uf! –

8

La instrucción x = ++x; escribe en la variable x dos veces antes de presionar sequence point y, por lo tanto, el comportamiento no está definido.

3

Es difícil imaginar un compilador que produzca el código para "x = ++ x;" que de hecho no funcionaría igual que "++ x".Sin embargo, si x no es volátil, sería legal que un compilador procesara la declaración "y = ++ x;" como

 
    y=x+1; 
    x=x+1; 

La declaración "x = ++ x;" se convertiría así en

 
    x=x+1; 
    x=x+1; 

Si tener el destino de una asignación de una expresión aritmética se acostumbre demasiado rápido como operando fuente para otro causaría un retraso tubería, la antigua optimización podría ser razonable. Obviamente desastroso si la variable incrementada y asignada es una y la misma.

Si la variable 'x' es volátil, no puedo pensar en ninguna secuencia de código donde un compilador que no intenta deliberadamente ser malo pueda legítimamente considerar "x = x ++;" como tener cualquier efecto que no sea leer todas las partes de 'x' exactamente una vez y escribir el mismo valor correcto para todas las partes de 'x' exactamente dos veces.

0

Supongo que, lógicamente, si escribe "x = ++ x" o "x = x ++", de cualquier manera esperaría que el resultado final sea que x es uno más de lo que comenzó. Pero hazlo un poco más complicado. ¿Qué pasa si escribió "x = x + (++ x)"? ¿Es esto lo mismo que "x = x + (x + 1)"? ¿O agregamos uno primero y luego agregamos x a sí mismo, es decir, "x = (x + 1) + (x + 1)"? ¿Qué pasa si escribimos "x = (x -) + (x ++)"?

Incluso si pudiera escribir una especificación de idioma que diera un significado inequívoco a este tipo de construcciones, y podría implementarlo limpiamente, ¿por qué lo haría? Poner un incremento unario en una asignación a la misma variable simplemente no tiene sentido, e incluso si lo forzamos a salir de él, no proporciona ninguna funcionalidad útil. Al igual, estoy seguro de que podríamos escribir un compliler que tome una expresión como "x + 1 = y-1" y descubrir que eso realmente significa "x = y-2", pero ¿para qué molestarse? No hay ganancia.

Incluso si escribiéramos compiladores que hicieran algo predecible con "x = x ++ - ++ x", los programadores tendrían que conocer y comprender las reglas. Sin ningún beneficio obvio, simplemente agregaría complejidad a los programas sin ningún propósito.

0

Para comprender esto, debe tener una comprensión básica de los puntos de secuencia. Vea este enlace: http://en.wikipedia.org/wiki/Sequence_point

Para el operador = no hay un punto de secuencia, lo que no hay garantía de que el valor de x será modificada antes de que se le asigna de nuevo a x.

Cuestiones relacionadas