2010-09-11 11 views
15

¿Por qué la compilación siguiente en C++?Operaciones previas múltiples en una variable en C++ (¿C?)

int phew = 53; 
++++++++++phew ; 

El mismo código falla en C, ¿por qué?

+0

Añadiendo la etiqueta C++ 0x solo por diversión. :) –

+1

Debe haber una pregunta estándar a la que podamos hacer referencia para este tipo de pregunta. Entonces, todas las preguntas (que obtenemos en esta época del año de nuevos estudiantes universitarios) pueden cerrarse rápidamente y marcarse leer esto. –

Respuesta

13

Eso es porque en C++ operador de incremento previo devuelve un lvalue y requiere su operando a ser un lvalue.

++++++++++phew ; de interpretarse como ++(++(++(++(++phew))))

Sin embargo su código invoca Undefined Behaviour ya que están tratando de modificar el valor de phew más de una vez entre dos sequence points.

En C, el operador pre-incremento devuelve un rvalue y requiere su operando ser un lvalue. Entonces su código no se compila en modo C.

+2

@Prasoon: Para no adivinarlo, solo tengo curiosidad por leer sobre lo que dijo; "Estás intentando modificar el valor de phew más de una vez entre dos puntos de secuencia". ¿Puede proporcionar una anotación a esta parte del estándar para que pueda leer más sobre esto? –

+3

@Merlyn Morgan-Graham: Lea este artículo de Steve Summit: http://c-faq.com/expr/seqpoints.html. –

+0

'Comentario ' Esta especificación solo debe seguirse exactamente cuando hay más de un acceso entre la secuencia puntos, o para objetos declarados con la clase de almacenamiento volátil. En lo que respecta al desarrollador, se produce una modificación de . Siempre que la implementación brinde el resultado esperado, es libre de hacer lo que le gusta. –

27

Nota: Los dos informes de defectos DR#637 y DR#222 son importantes para entender el siguiente razonamiento es el comportamiento.


Para la explicación, en C++ 0x hay value computations y side effects. Un efecto secundario, por ejemplo, es una asignación, y un cálculo de valor es determinar a qué se refiere un valor l o leer el valor de un valor l. Tenga en cuenta que C++ 0x ya no tiene puntos de secuencia y esto está redactado en términos de "secuencia antes"/"secuencia después". Y se afirma que

Si un efecto secundario en un objeto escalar es unsequenced en relación con cualquiera otro efecto secundario sobre el mismo objeto escalar o un cálculo de valor con el valor del mismo objeto escalar, el comportamiento no está definido.

++v es equivalente a v += 1 que es equivalente a v = v + 1 (excepto que v sólo se evalúa una vez). Esto cede a ++ (v = v + 1) que voy a escribir como inc = inc + 1, donde inc se refiere al resultado lvalue de v = v + 1.

En C++ 0x ++ ++v no es un comportamiento indefinido porque para a = b la asignación se secuencia después del cálculo del valor de by a, pero antes del cálculo del valor de la expresión de asignación. Se deduce que la asignación en v = v + 1 se secuencia antes del cómputo de valor de inc. Y la asignación en inc = inc + 1 se secuencia después del cálculo del valor de inc. Al final, ambas tareas serán secuenciadas y no hay un comportamiento indefinido.

+3

Buena respuesta. Del mismo modo 'int a = 4; ++ a = 5; 'no invocaría a UB en C++ 0x, ¿verdad? –

+0

@Prasoon sí. Establecería 'a' en 5. Del mismo modo' a = ++ a; 'no será UB, pero' a = a ++; 'será UB. –

+0

@Johannes: Genial :-). El mundo esta cambiando. –