9

In Delphi, consider

var
  i: integer;

begin

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

One might think that i = N after the for loop, but does the Delphi compiler guarantee this? Can one make the assumption that the loop variable is equal to its last value inside the loop, after a Delphi if loop?

Update

After trying a few simple loops, I suspect that i is actually equal to one plus the last value of i inside the loop after the loop... But can you rely on this?

4
  • Are you even certain that N is in scope after the for loop? I would check this first - because I suspect it may not be. Commented Apr 9, 2010 at 21:04
  • @LBushkin: That depends on how N is declared. But in the above code example I only use N as a "placeholder" for whatever might be the last value of the loop variable. Commented Apr 9, 2010 at 21:09
  • @LBushkin, you can be absolutely certain that N will be in scope after the loop because it was obviously in scope before the loop (or else the code wouldn't have compiled). Scope in Delphi doesn't change mid-function; it starts at the start of a function and ends at the end. Commented Apr 10, 2010 at 14:47
  • > But can you rely on this? - NO Commented May 27, 2010 at 21:00

7 Answers 7

27

No, Delphi does not guarantee any value. Outside the loop, the variable is undefined - and IIRC the Language Guide excplicitly state so - that means that newer compiler implementations are free to change whatever value the variable may have outside the loop due to the actual implementation.

Sign up to request clarification or add additional context in comments.

10 Comments

That is correct. The variable is specifically documented to be undefined after the loop is complete. If you need a defined variable after the loop, use while or repeat
Depending upon how the loop variable is used within the loop, the compiler may even eliminate it completely and simply use a pointer to iterate through the elements of an array, for example.
... is undefined ... except if you terminate the loop with the 'break' statement. In that case, value is defined (the last value the loop counter had before the 'break' was executed).
Gabr is right. If you leave the loop with break, the control variable's value will be valid. Likewise if you leave the loop with exit. The documentation says so. Undocumented, but still generally accepted as true, is that leaving the loop via raise or goto will also preserve the variable's value.
If the variable isn't used inside the loop, the compiler might generate code that counts from N to 0 even if the source says to count from 0 to N, because that is slightly more efficient. I have no idea what value the variable would have after the loop in that case.
|
8

The compiler actually emits a warning if you use the loop variable after the loop, so you should consider it undefined.

Comments

6

I would suggest that using a while loop is clearer if you need to use the loop index after the loop:

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

After that loop terminates, you know that i will be N + 1 (or greater, if N could have been less than zero).

2 Comments

Yes, that is a very good method. After all, every for loop can be written as a while loop in this way, but without any "compiler magic".
You could use Inc(i) instead of i := i + 1, but IIRC the compiler will treat them the same anyway.
2

It is even documented that the loop variable from a for loop is undefined outside the loop.

In practice: What you get from the variable varies depending on compiler settings and code complexity. I have seen changes in code push the compiler into a different optimization path, therefore modifying the value of this undefined variable.

--jeroen

Comments

1

As many people stated, the I variable is supposed to be undefined after the loop. In real world usage, it will be defined to the last value it had before you "break", or to N + 1 if loop run to term. That behavior cannot be relied on though, as it's clearly specified it's not meant to work.

Also, sometimes, I won't even be assigned. I encountered this behavior mostly with optimisation turned ON.

For code like this

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

So... If you want to know the value of I after the loop, it's better practice to assign it to another variable before going out of the loop.

Comments

1

NEVER EVER rely on the value of the for variable, after the loop.

Check your compiler output. Delphi compiler warns you about that. Trust your compiler.

  1. NEVER hide your compiler's hints and warnings with {$Warnings off}!
  2. Learn to treat the info as warnings and the warnings as errors!
  3. Optimize your code until you have ZERO hints and warnings (without violating rule 1).

6 Comments

Well, this is perhaps a bit too "strict". For instance, in many cases the warning "return value of function ... might be undefined" is irrelevant.
It's very rare that the compiler says something may be undefined when that's not possible. The only cases I've seen involve two conditionals that assign results and inherently one of them must run. I consider it worth a bit of extra code to suppress ALL warnings even when I know they are harmless.
This happens often if you raise an exception inside the function, or if you mix the Exit(ReturnValue) method with the old-school result := method.
"For instance, in many cases the warning "return value of function ... might be undefined" is irrelevant" - learn to initialize that variable. Anyway, these case are not so many.
"I consider it worth a bit of extra code to suppress ALL warnings even when I know they are harmless." - Isn't nice to have a clean compiler output? :)
|
0

As its been stated before, its undefined and can behave funnily if the variable has a value assigned before the for loop. If you exit the for loop with a Break; then the value is correct in all cases.

In our experience, in FreePascal, the value of the loop variable tends to be the "to" value, but in embarcadero (former borland), the value is often "to" + 1.

I wonder why no pascal compiler gives you even a warning regarding this issue, as its going to cause certain mayhem.

2 Comments

Actually, most Delphi compilers give you such a warning: docwiki.embarcadero.com/RADStudio/en/…
@dummzeuch Thanks for the tip, Free Pascal / Lazarus does not warn you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.