Considere la siguiente instrucción. ¿Cuál será el valor almacenado en b?uso de operador condicional
int a=1;
int b = a+=1 ? a+=1 : 10;
Me sale la respuesta como 4. ¿Alguien puede explicar cómo funciona eso por favor?
Considere la siguiente instrucción. ¿Cuál será el valor almacenado en b?uso de operador condicional
int a=1;
int b = a+=1 ? a+=1 : 10;
Me sale la respuesta como 4. ¿Alguien puede explicar cómo funciona eso por favor?
Tiene que ver con la precedencia. Si se examina el siguiente código (con el extremo derecho a+=1
cambiado por simplicidad):
#include <iostream>
int main (void) {
int a=1;
int b = a+=1 ? 7 : 10;
std::cout << b << std::endl;
return 0;
}
verá que la salida es 8
, no 7
o 10
.
Eso es debido a que la declaración:
int b = a+=1 ? 7 : 10;
se interpreta como:
int b = (a += (1 ? 7 : 10));
Ahora, aplicándolo a su caso, obtenemos:
int b = (a += (1 ? a += 1 : 10));
y, con el fin de ejecución:
a += 1
(desde 1
es verdadero) establece a
en 2
.a += 2
(2
es el resultado del paso anterior) establece a
en 4
.b = 4
(4
es el resultado del paso anterior).Solo tenga en cuenta que no necesariamente puede confiar en ese orden de evaluación. Aunque hay un punto de secuencia en ?
(por lo que 1
se evalúa por completo antes de continuar), no hay punto de secuencia entre el extremo derecho a += ...
y el extremo izquierdo a += ...
. Y la modificación de una sola variable en dos ocasiones sin un punto de secuencia intermedia es un comportamiento indefinido, que es la razón por gcc -Wall
le dará el mensaje de gran utilidad:
warning: operation on ‘a’ may be undefined
El hecho de que se le da 4
es pura coincidencia. Se podría fácilmente dar 3
, 65535
o incluso formatear el disco duro para darle una lección :-) análisis
@shreedhar: Sí, he eliminado mi comentario. Esta respuesta parece ser correcta. –
BTW g ++ me da una advertencia "la operación en' a' puede no estar definida ". –
@Prasoon: Eso es porque 'a + = a + = 1' no está definido. – ephemient
Asamblea: Código
int main()
{
int a=1;
int b = a+=1 ? a+=1 : 10;
return 0;
}
Asamblea generada (utilizando MinGW) para el código anterior es mostrado a continuación. ¡Los comentarios son míos, por supuesto! Lee los comentarios también!
call ___main //entering into main()
movl $1, 12(%esp) //int a = 1; means 12(%esp) represents a;
incl 12(%esp) //a+=1 ; a becomes 2
movl 12(%esp), %eax //loading 'a' onto a register(eax); eax becomes 2
addl %eax, %eax //adding the register to itself; eax becomes 4
movl %eax, 12(%esp) //updating 'a' with the value of eax; 'a' becomes 4
movl 12(%esp), %eax //this step could be optimized away; anyway it loads value of 'a' onto the register(eax); eax becomes 4, in fact even earlier it was 4 too! needless step!
movl %eax, 8(%esp) //loading the value of eax at another memory location which is 8(%esp); this location represents b;
movl $0, %eax //making eax zero! the return value of main()!
leave //now main() says, please leave me!
12(%esp)
representan la ubicación de memoria de a
, y en un byte distancia 4 de ella, es decir, 8(%esp)
representa b
. Al final, el valor en ambas ubicaciones de memoria es 4.
Por lo tanto, b = 4. También a = 4.
Como se indica en las otras respuestas estos dos fragmentos de código son equivalentes debido a las reglas de la gramática de C++ que determinan cómo las expresiones compuesto debe ser analizada.
int a=1;
int b = a+=1 ? a+=1 : 10;
y
int a=1;
int b = (a += (1 ? (a += 1) : 10));
Aunque hay un punto de secuencia en un condicional-expresión es entre la evaluación de la primera expresión (1
) y la evaluación de lo que uno de los segundos y tercera expresiones se evalúa (a += 1
en este caso). No hay un punto de secuencia extra explícito después de la evaluación de la segunda o tercera expresión.
Esto significa que a
es modificado dos veces en el inicializador para b
sin un punto de secuencia intermedia por lo que el código tiene comportamiento indefinido.
Esta es la respuesta correcta. Buena captura Charles. :) +1 –
Comportamiento indefinido. – GWW
@GWW: ¡No! [....] –
"¿Alguien puede explicar cómo funciona eso por favor?" >> Ciertamente no puedo, pregúntele al programador que lo escribió. Y nunca le pidas que escriba nada de nuevo. :) – Mehrdad