¿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é?
¿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é?
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.
@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? –
@Merlyn Morgan-Graham: Lea este artículo de Steve Summit: http://c-faq.com/expr/seqpoints.html. –
'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. –
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.
Buena respuesta. Del mismo modo 'int a = 4; ++ a = 5; 'no invocaría a UB en C++ 0x, ¿verdad? –
@Prasoon sí. Establecería 'a' en 5. Del mismo modo' a = ++ a; 'no será UB, pero' a = a ++; 'será UB. –
@Johannes: Genial :-). El mundo esta cambiando. –
Añadiendo la etiqueta C++ 0x solo por diversión. :) –
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. –