¿Bug en delphi?

Me encontré con este misterio en delphi y necesito una solución.
Fíjate en este simple código:
var
i,a: integer;
begin
i:= 0;
a:= 0;
for i:= 1 to 10 do
a:= a * 2;
end;
Lo misterioso del asunto es que el contador va contando hacia atrás,
es decir 10,9,8.. ¿1 se trata de un bug?
En la parte de abajo de la ventana de código me muestra:
Value assigned to 'i' never used
¿Cómo soluciono este drama?
Desde ya muchas gracias.
3

3 Respuestas

0 pts.
Ya veo a qué te refieres. Efectivamente, si no usas el valor de i, la optimización del compilador hace que el bucle sea hacia atrás, debido a que seguramente en ensamblador la traducción resulta así más eficiente.
Pero no te preocupes, si utilizas el valor de i, todo funcionará correctamente. No tienes más que probarlo.
Si fuera un bug, estaría ya más que detectado, ya que un bucle for se usa en prácticamente todos los programas. Ya se habrían dado cuenta hace mucho!
A ver, esta pregunta que me haces es francamente extraña. Hasta me pareció una broma.
Ni el contador cuenta hacia atrás, ni nada. De entrada, ¿cómo sabrías que cuenta hacia atrás? ¿Lo has debugueado? Pues yo lo he hecho y va como un reloj 1,2...
En cuanto al mensaje "Value assigned to 'i' never used " es normal, porque es cierto. No utilizas la variable i en ningún cálculo, sólo la usas para contador del bucle, pero los distintos valores que va tomando no los usas. Tampoco es que sea un drama. Es un aviso del compilador, para señalarlo por si acaso, pero no un error.
En cuanto al valor de a, me imagino que no te extraña que el resultado sea siempre cero, ya que lo inicializas a cero, y por mucho que lo multipliques, cero por cualquier otro número es cero.
En fin, que no sé si te soy de ayuda, y que tu pregunta me dejó algo perplejo...
5.525 pts.
No es un bug, es simplemente que Delphi optimiza el código.
Es más eficiente que el contador se decremente que se incremente porque a nivel de código máquina es mejor iniciar el contador con el número de vueltas en el bucle.
La instrucción LOOPZ, de ensamblador 80x86, es la que emplea Delphi en estos casos, iniciando el registro ECX con el número total de vueltas en el bloque, al llegar al final del bucle y si este es cero se sale del bucle, si no se decrementa y se vuelve al inicio del bucle.
Ahora bien, Delphi solo aplica esta optimización si no utilizas la variable de contador, si la refieres dentro del bucle, fuerzas a Delphi a utilizar otro modo de compilación.
Si por ejemplo, a tu código lo modificas y escribes:
var
i,a: integer;
begin
i:= 0;
a:= 0;
for i:= 1 to 10 do
a:= i * a * 2;
end;
Verás como ahora la variable "i" si que toma los valores que esperas. Es lógico e incluso inteligente como actúa el compilador de Delphi. Por algo, es uno de los que producen el código más rápido del mercado.
El mensaje (HInt) "Value assigned to 'i' never used", es totalmente normal e indica que no usas la variable "i" en ningún sitio. No tiene importancia, porque es realmente lo que quieres hacer. Ignora este aviso.
Puedes desactivar la optimización del código (no te lo recomiendo) desde el menú:
Project >> Options >> Pestaña Compiler >> Code Generation [ Optimatization ]
También puedes desactivar los HInts desde:
Project >> Options >> Pestaña Compiler Messages >> Show Hints
Finalmente, como corolario, que la conclusión que se puede llegar es que se realicen los bucles decrementando la variable contador. De esta manera, si Delphi no optimiza por nosotros porque estemos usando la variable (referenciandola) de manera automática si que estaremos forzando un poco a que se optimice.
6.675 pts. Analista y programador, Experto en Delphi con 8 años de...
Es cierto! Nunca lo había visto. El mensaje "Value assigned to 'i' never used"
Lo da la primer linea i:= 0 que es removida en la optimización que realiza delphi al compilar. Esto lo ves poniendo un punto de debug en esa linea, veras que nunca se ejecuta. En cuanto al otro problema, debe ser alguna optimización que realiza el compilador porque nunca usas el indice de incremento en la iteración.Es decir si cambias el código por
var
i,a: integer;
begin
a:= 0;
for i:= 1 to 10 do
a:= a * i;
end;
Veras que i gana valores de 1 a 10. En cuanto lo que tu encontraste, un misterio voy a consultarlo con amigos a ver si alguien sabe el motivo.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas