Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   ¿Por que funciona al revés el "For to"? (https://www.clubdelphi.com/foros/showthread.php?t=77048)

AzidRain 16-12-2011 02:50:40

¿Por que funciona al revés el "For to"?
 
Depurando un código me encontré con este comportamiento raro, primero veamos la imagen:

La variable i como vemos la inicializo "a fuerza" en 1 antes de entrar al bucle, como podemos ver, ya dentro del bucle teóricamente la variable tendría que ir valiendo desde 1 hasta 12, sin embargo como se ve en el watchlist empieza en 12!! Si seguimos dando F8 para irnos paso a paso la variable va disminuyendo hasta 1, es decir, como si hubiera puesto un "For downto".

¿Alguien tiene alguna idea de por qué pasa esto o a alguien más le ha pasado?

Al González 16-12-2011 03:57:40

Hola César.

Esto se debe a la manera en que el compilador genera el código máquina. A fin de optimizar éste, si la variable contador no es referida dentro del For, su existencia es obviada y el código máquina solamente cumple el requisito de repetir el ciclo tantas veces como la cabecera del for lo indica.
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
Var
  I :Integer;
begin
  For I := 1 To 12 Do
    Caption := Caption + 'x';
end;

En cambio, si la variable contador es referida dentro del ciclo, ésta contendrá el valor que se espera.
Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);
Var
  I :Integer;
begin
  For I := 1 To 12 Do
    Caption := Caption + IntToStr (I);
end;

Puedes comprobar lo que hay detrás de segmentos de código como los anteriores, ejecutando paso a paso y mirando la ventana CPU del depurador. Notarás que para el primero usa una instrucción DEC mientras que para el segundo emplea una instrucción INC.

Como dato adicional, algo de la ayuda de Delphi que lleva cierta relación con el tema:
Cita:

Empezado por apartado "For statements"
After the for statement terminates (provided this was not forced by a break or an exit procedure), the value of counter is undefined.

Saludos y que haya concluido aquella restricción de teclados. :)

Al González.

Crandel 16-12-2011 04:52:34

Cita:

Empezado por Al González (Mensaje 421321)
Esto se debe a la manera en que el compilador genera el código máquina. A fin de optimizar éste, si la variable contador no es referida dentro del For, su existencia es obviada y el código máquina solamente cumple el requisito de repetir el ciclo tantas veces como la cabecera del for lo indica.

ok, eso es asi. Pero en su caso si utiliza la variable i dentro de su ciclo, salvo que lo halla modificado en tiempo de ejecución.

Un poco extraño lo que sucede.

Delphius 16-12-2011 05:01:32

Cita:

Empezado por Crandel (Mensaje 421322)
ok, eso es asi. Pero en su caso si utiliza la variable i dentro de su ciclo, salvo que lo halla modificado en tiempo de ejecución.

Un poco extraño lo que sucede.

Tengo entendido que mientras el compilador determine que no exista alguna condición de "orden" o que afecte o condicione la relación entre las sentencias que forman a bloque por más que se referencie la variable dentro dentro del ciclo seguirá implementando, internamente por optimización, un ciclo descendente.

Es decir: a menos que existan instrucciones que afecten el flujo normal de las operaciones, o mientras no existe cierta dependencia de orden entre las propias instrucciones el for será descendente.

Si te fijas en la imagen, da lo mismo que se empiece por CampoDif[1] como por campoDif[12]... siempre logrará hacerlo, en cualquier sentido. Distinto sería si por ejemplo el valor i-ésimo se viera afectado por alguna otra condición o dependencia incluso de algún otro CampoDif[j-ésimo].

Otra manera de "forzar" el for a seguir el camino correcto es desactivar la optimización.

Saludos,

Al González 16-12-2011 16:56:06

Cita:

Empezado por Crandel (Mensaje 421322)
ok, eso es asi. Pero en su caso si utiliza la variable i dentro de su ciclo, salvo que lo haya modificado en tiempo de ejecución.

Un poco extraño lo que sucede.

Gracias por la observación, Crandel. Es como si esa I no fuera esa I, algo está faltando...

Delphius: Lo que dices tiene lógica, pero creo que sería muy difícil para el compilador determinar si una referencia de la variable contador dentro del ciclo puede o no puede alterar el resultado de las cosas, cuando tal referencia forma parte de una expresión como "FieldByName...AsFloat". Asumiendo que estamos hablando del FieldByName de TDataSet, esas sentencias involucran llamadas a varios métodos virtuales que según su implementación podrían realizar cualquier cosa. Dichos métodos serían ejecutados en primer lugar con un campo o con otro, dependiendo de si la variable es incrementada o disminuida.

En un código como el que ha mostrado AzidRain, el compilador no debería realizar la optimización mencionada.

César, ¿qué versión del compilador es? Y, aunque la pregunta parezca tonta, ¿el código que muestras es real? ¿Podrías pegar más del mismo aquí?

Saludos.

AzidRain 16-12-2011 20:31:28

Gracias por las respuestas, luego les traigo otras más a modo de curiosidades.


La franja horaria es GMT +2. Ahora son las 13:04:45.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi