2010-04-09 20 views
8

En Delphi, considere¿Qué es la variable de bucle después de un bucle for en Delphi?

var 
    i: integer; 

begin 

    for i := 0 to N do 
    begin 
    { Code } 
    end; 

Uno podría pensar que i = N después del bucle for, pero sí la garantía compilador de Delphi esto? ¿Se puede suponer que la variable de bucle es igual a su último valor dentro del bucle, después de un bucle Delphi if?

actualización

Después de probar unos bucles simples, sospecho que i es en realidad igual a uno más el último valor de i dentro del bucle después del bucle ... ¿Pero se puede confiar en esta ?

+0

¿Está seguro de que N está en el alcance después del bucle 'for'? Verificaría esto primero, porque sospecho que puede no ser así. – LBushkin

+0

@LBushkin: Eso depende de cómo se declare N. Pero en el ejemplo del código anterior, solo uso * N * como un "marcador de posición" para cualquiera que sea el último valor de la variable de ciclo. –

+0

@LBushkin, puede estar absolutamente seguro de que 'N' estará en el alcance después del bucle porque obviamente estaba dentro del alcance antes del bucle (o el código no se habría compilado). El alcance en Delphi no cambia la función media; comienza al comienzo de una función y termina al final. –

Respuesta

23

No, Delphi no garantiza ningún valor. Fuera del ciclo, la variable no está definida, y IIRC, la Guía de idiomas lo establece explícitamente, eso significa que las nuevas implementaciones del compilador son libres de cambiar cualquier valor que la variable pueda tener fuera del ciclo debido a la implementación real.

+5

Eso es correcto. La variable está específicamente documentada para ser indefinida después de que se completa el ciclo. Si necesita una variable definida después del bucle, use while o repeat –

+3

Dependiendo de cómo se use la variable de bucle dentro del bucle, el compilador incluso puede eliminarla completamente y simplemente usar un puntero para iterar a través de los elementos de una matriz, por ejemplo . –

+0

+1 ¡desde que Nick dijo que estás en lo correcto! –

6

Yo sugeriría que el uso de un bucle while es más clara si necesita utilizar el índice de bucle después del bucle:

i := 0; 
while i <= N 
begin 
    { Code } 
    i := i + 1; 
end; 

Después termina ese bucle, que sabe que i habrá N + 1 (o mayor , si N podría haber sido menor que cero).

+0

Sí, es un método muy bueno. Después de todo, cada ciclo for se puede escribir como un ciclo while de esta manera, pero sin ningún "magic compilador". –

+2

Puede usar 'Inc (i)' en lugar de 'i: = i + 1', pero IIRC el compilador los tratará igual de todos modos. –

7

El compilador realmente emite una advertencia si usa la variable de bucle después del bucle, por lo que debería considerarlo indefinido.

2

Es incluso documented que la variable de bucle de un for bucle no está definida fuera del bucle.

En la práctica: Lo que obtienes de la variable varía según la configuración del compilador y la complejidad del código. He visto cambios en el código que empujan al compilador hacia una ruta de optimización diferente y, por lo tanto, modifican el valor de esta variable indefinida.

--jeroen

1

Como muchas personas afirmaron, se supone que la variable que no está definido después del bucle. En el uso del mundo real, se definirá con el último valor que tenía antes de "romper", o con N + 1 si el ciclo se ejecuta a término. Sin embargo, no se puede confiar en ese comportamiento, ya que está claramente especificado que no debe funcionar.

Además, a veces, I ni siquiera serán asignados. Encontré este comportamiento principalmente con la optimización activada.

Para código como este

I := 1234; 
For I := 0 to List.Count - 1 do 
begin 
    //some code 
end; 
//Here, I = 1234 if List.Count = 0 

Entonces ... Si quieres saber el valor de I después del bucle, es mejor práctica para asignarlo a otra variable antes de salir del bucle.

1

NUNCA SIEMPRE confíe en el valor de la variable para, después del ciclo.

Compruebe la salida de su compilador. El compilador Delphi te advierte sobre eso. Confía en tu compilador.

  1. NUNCA oculte los consejos y advertencias de su compilador con {$ Warnings off}!
  2. ¡Aprenda a tratar la información como advertencias y advertencias como errores!
  3. Optimice su código hasta que tenga CERO sugerencias y advertencias (sin violar la regla 1).
+0

Bueno, esto es quizás un poco demasiado "estricto". Por ejemplo, en muchos casos, la advertencia "valor de retorno de la función ... podría no estar definido" es irrelevante. –

+0

Es muy raro que el compilador diga que algo puede estar indefinido cuando eso no es posible. Los únicos casos que he visto involucran dos condicionales que asignan resultados e inherentemente uno de ellos debe ejecutarse.Considero que vale la pena un poco de código adicional para suprimir * TODAS * las advertencias, incluso cuando sé que son inofensivas. –

+1

Esto ocurre a menudo si 'raise' una excepción dentro de la función, o si mezcla el método 'Exit (ReturnValue)' con el método 'result: =' de la vieja escuela. –

Cuestiones relacionadas