2010-04-09 38 views
8

W Delphi, należy rozważyćCo to jest zmienna pętli po pętli w Delphi?

var 
    i: integer; 

begin 

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

Można by pomyśleć, że i = N po pętli for, ale robi to gwarancja kompilator Delphi? Czy można przyjąć założenie, że zmienna pętli jest równa jej ostatniej wartości w pętli, po pętli Delphi if?

Aktualizacja

Po wypróbowaniu kilku prostych pętle, podejrzewam, że i jest faktycznie równa jeden plus ostatniej wartości i wewnątrz pętli po pętli ... Ale można liczyć na to ?

+0

Czy jesteś pewien, że N jest w zasięgu po pętli 'for'? Najpierw sprawdzę to, bo podejrzewam, że tak nie jest. – LBushkin

+0

@LBushkin: To zależy od tego, jak zadeklarowano N. Ale w powyższym przykładzie kodu używam tylko * N * jako "symbolu zastępczego" dla jakiejkolwiek może być ostatniej wartości zmiennej pętli. –

+0

@LBushkin, możesz być absolutnie pewien, że 'N' będzie w zasięgu po pętli, ponieważ było to oczywiście w zasięgu przed pętlą (inaczej kod nie zostałby skompilowany). Zakres w Delphi nie zmienia się w połowie funkcji; zaczyna się na początku funkcji i kończy na końcu. –

Odpowiedz

23

Nie, Delphi nie gwarantuje żadnej wartości. Poza pętlą zmienna jest nieokreślona - a IIRC Przewodnik językowy to jawnie stwierdza - co oznacza, że ​​nowsze implementacje kompilatorów mogą dowolnie zmieniać dowolną wartość, jaką zmienna może mieć poza pętlą ze względu na faktyczną implementację.

+5

To prawda. Zmienna jest specjalnie udokumentowana jako niezdefiniowana po zakończeniu pętli. Jeśli potrzebujesz określonej zmiennej po pętli, użyj while lub repeat –

+3

W zależności od tego, jak zmienna pętli jest używana w pętli, kompilator może nawet całkowicie ją wyeliminować i po prostu użyć wskaźnika do iteracji elementów tablicy, na przykład . –

+0

+1 od kiedy Nick powiedział, że masz rację! –

6

Sugerowałbym, że stosując while pętli jest wyraźniejszy, jeśli trzeba użyć indeksu pętli po pętli:

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

Potem pętla kończy, znasz że i będzie N + 1 (lub większa , jeśli N może być mniejszy od zera).

+0

Tak, to jest bardzo dobra metoda. Wszakże każda pętla for może być zapisana w ten sposób jako pętla while, ale bez "magii kompilatora". –

+2

Możesz użyć 'Inc (i)' zamiast 'i: = i + 1', ale IIRC kompilator potraktuje je tak samo. –

7

Kompilator faktycznie wysyła ostrzeżenie, jeśli po pętli używasz zmiennej pętli, więc powinieneś ją uznać za niezdefiniowaną.

2

To nawet documented, że zmienna pętli z pętli for jest niezdefiniowana poza pętlą.

W praktyce: To, co otrzymasz ze zmiennej, zależy od ustawień kompilatora i złożoności kodu. Widziałem zmiany w kodzie, popchnij kompilator na inną ścieżkę optymalizacji, modyfikując wartość tej niezdefiniowanej zmiennej. stwierdził

--jeroen

1

Jak wiele osób, zmienna I ma być niezdefiniowana po pętli. W prawdziwym świecie będzie on zdefiniowany do ostatniej wartości, którą miał przed "zerwaniem", lub do N + 1, jeśli pętla uruchomi się na czas. Na to zachowanie nie można polegać, ponieważ jest jasno określone, że nie ma działać.

Czasami, I nie będzie nawet przypisany. Napotkałem to zachowanie głównie z włączoną optymalizacją.

Dla kodu jak ten

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

więc ... Jeśli chcesz poznać wartość I po pętli, to lepiej praktyka przypisać go do innej zmiennej przed wyjściem z pętli.

1

NIGDY nie polegaj na wartości zmiennej for po pętli.

Sprawdź dane wyjściowe kompilatora. Kompilator Delphi ostrzega o tym. Zaufaj kompilatorowi.

  1. NIGDY nie ukrywaj wskazówek i ostrzeżeń kompilatora za pomocą {$ Ostrzeżenia wyłączone}!
  2. Dowiedz się, jak traktować informacje jako ostrzeżenia i ostrzeżenia jako błędy!
  3. Zoptymalizuj swój kod, dopóki nie otrzymasz ZERO wskazówek i ostrzeżeń (bez naruszenia zasady 1).
+0

Cóż, to może trochę zbyt "surowe". Na przykład w wielu przypadkach ostrzeżenie "zwracana wartość funkcji ... może być nieokreślone" nie ma znaczenia. –

+0

Bardzo rzadko zdarza się, że kompilator mówi, że coś może być nieokreślone, gdy nie jest to możliwe. Jedyne przypadki, które widziałem, dotyczą dwóch czynników warunkujących, które przypisują wyniki i z natury jeden z nich musi działać.Uważam, że warto dodać trochę dodatkowego kodu, aby ukryć ostrzeżenia * ALL *, nawet jeśli wiem, że są nieszkodliwe. –

+1

Zdarza się to często, gdy 'podniesiesz' wyjątek wewnątrz funkcji lub gdy miksujesz metodę' Exit (ReturnValue) 'z oldschoolową' result: = 'method. –

Powiązane problemy