c++ - i=i++; es indefinido. ¿Es i=foo(i++) también indefinido?
undefined-behavior (2)
La última oración de su cita dice "que no está secuenciada específicamente antes o después de la ejecución del cuerpo de la función llamada" por lo que la pregunta es si el incremento y la asignación "están secuenciadas específicamente antes o después" del cuerpo de la función.
1.9 [intro.execution] p15 tiene la respuesta:
Cuando se llama a una función (ya sea que la función esté o no en línea), cada cálculo de valor y efecto secundario asociado con cualquier expresión de argumento, o con la expresión de posfijo que designa la función llamada, se secuencia antes de la ejecución de cada expresión o declaración en el cuerpo del llamada función. [ Nota: los cálculos de valor y los efectos secundarios asociados con diferentes expresiones de argumentos no tienen secuencia. - nota final ]
Entonces, el incremento de i
ocurre antes del cuerpo de la función, y la asignación a i
ocurre después de que la función regresa, por lo que está perfectamente bien definida.
En la terminología anterior a C ++ 11, la llamada a la función introduce un punto de secuencia entre el incremento y la asignación.
Por ejemplo:
int foo(int i) { return i; }
int main()
{
int i = 0;
i = i++; // Undefined
i = foo(i++); // ?
return 0;
}
¿Qué especificaría la norma ISO C ++ actual para este caso?
EDITAR:
Aquí es donde me confundo:
Excepto donde se indique, las evaluaciones de los operandos de operadores individuales y de las subexpresiones de expresiones individuales no tienen secuencia.
Si un efecto secundario en un objeto escalar no tiene secuencia en relación con otro efecto secundario en el mismo objeto escalar o un cálculo de valor utilizando el valor del mismo objeto escalar, y no son potencialmente concurrentes (1.10), el comportamiento no está definido.
En todos los casos, la asignación se secuencia después del cálculo del valor de los operandos derecho e izquierdo, y antes del cálculo del valor de la expresión de asignación
Cada evaluación en la función de llamada (incluidas otras llamadas de función) que no está secuenciada específicamente antes o después de la ejecución del cuerpo de la función llamada se secuencia de forma indeterminada con respecto a la ejecución de la función llamada.
Así que parece que podría tener un cálculo de valor en el lado izquierdo de la asignación (solo i
), y un efecto secundario en el lado derecho (la modificación de i
de i++
) que no están secuenciados uno con respecto al otro.
EDIT2 :
Para cualquier persona que se encuentre aquí, hay una gran explicación sobre la secuenciación que encontré here .
i = foo(i++);
está bien, porque i++
se ejecuta antes de llamar a foo()
. Se crea una copia de i
, luego se incrementa, luego la copia se pasa a foo()
. Es lo mismo que hacer esto explícitamente:
int tmp = i++;
i = foo(tmp);