http://www.perlmonks.org?node_id=317485


in reply to Re: Re: for loop localisation bug?
in thread for loop localisation bug?

I beg to differ, at least as far as C is concerned.

#include <stdio.h> void main() { int n; for( n=0; n<10; n++ ) { printf( "%d\n", n ); if( n == 5 ) break; } printf( "Residual value: %d\n", n ); } __END__ P:\test>bcc32 test.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland test.c: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland P:\test>test 0 1 2 3 4 5 Residual value: 5

And even in languages that allow the loop variable to be declared within the for loop initialiser statement, it's scope is not that of the for loop body, but that of the enclosing block.

From p.38 of "Programming in C++ by Stephen C. Dewhurst & Kathy T. Stark"

Declarations are statements and can appear any place a statement can within a block. This flexibility allows names to be declared and initialised at the point of their first use. For example, the first clause in a for loop control is a statement so a loop index can be declared there.
for( int i = 0; i < limit; i++ ) { // etc. } return i;

The scope of the name extends from its point of declaration to the end of the enclosing block. Notice that in this example, i is still available after the loop terminates. It goes out of scope at the end of the block that contains the for statement.

I don't have a Pascal reference handy, but I seem to recall (from a very long time ago) that it's for loop acted similarly.


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Hooray!

Replies are listed 'Best First'.
Re: Re: Re: Re: for loop localisation bug?
by BUU (Prior) on Dec 29, 2003 at 20:07 UTC
    I have absolutely no evidence here, but all your example proves is that specific implementation retains the value in the loop iterator. I don't have the C spec handy so I have nothing to prove that Corion is right, but I too seem to recall something along those lines, that the loop iterator is undefined after the loop and so it's best practice not to rely on it, regardless that it's defined for probably 95% of the compilers.

      Sorry, but I think you are wrong on this. Checking both K&R (the original version from circa. 1978) and the ANSI C specification, particularly Scopes of identifiers and Iteration statements, I can find nothing to support your position.

      Identifiers in C are block scoped, the iterator variable in a for loop must be declared prior to the for loop and there is nothing special about it. It retains the last value set until that value is changed, regardless of whether the statement that changed it is a simple assignment, inside or outside of a loop body, or even as one of the three statements that make up the for loop control statements. It remains in scope and defined until the block at which it was defined is exited.

      It is never undefined, and any such statement of 'best practice' is simply ignoring both the design specification and the realities of implementations. It buys you nothing.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Hooray!

        ANSI/ISO/IEC Standard 9899:1999 (C99 Standard) (Link to ANSI's Store) allows allocation of the identifer in the for statement and scopes the identifer to the loop only

        This code is now legal in C99 compilers (which to my knowledge there are not very many)

        for(int i=0; i < 100; i++){ /*do some thing with i */ printf("this is i: %d", i); }

        and it is lexically the same as:

        { int i; for(i=0; i < 100; i++){ /*do something here with i */ printf("this is i: %d", i); } }
        **This code is Not Tested (even for correctness)**
        Note that the second code sinpet is blocked, limiting the scope of i in the for statement. References are the Swedish Instute of Computer Science (which posted the C99 Standard here (a PDF) if this is not a legal posting please remove link)
        6.8.5.3 is the paragraph dealing with the FOR statement

        And this overview of C99

        This does NOT invalidate your argument about pre c99 compilers or non-complying compilers. And if you declare your iterator loop varable before the for loop it will work the same as it did previouly. I point this out because I think that this is what these other fine Monks must be thinking of.

        MADuran who must now find a spiffy sig.

Re: Re: Re: Re: for loop localisation bug?
by Corion (Patriarch) on Dec 29, 2003 at 23:18 UTC

    After some searching, I found this link for Pascal, which tells what I know about Pascal, that the value is undefined after leaving the loop. I think that Turbo Pascal and Borland Pascal had the value of the upper bound of the loop at the end of the loop, but confusion started once they implemented optimizations in BP7 and Delphi.

    For C, I browsed the standard a bit, but didn't stumble on anything going in either direction, so I guess the behaviour is neither implementation defined nor undefined but merely unspecified (some FAQ goes to some lengths to explain the differences between these three regarding the ANSI C standard...). I guess that one will find ugly differences soon enough if one uses enough different compilers and not only gcc...

    The same pages as for the Pascal link give some remarks about C loops, but also no hint as to what the value of the loop iterator is after leaving the loop.

    perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web

      I said my Pascal was a long time ago:) I dug up a little info on the last Pascal compiler I used -- in a museum!

      For C, I think the info I dug up and posted here is reasonably definitive. With deference to MADuran's info on C99 which I've never encountered, there is no definitive statement on the state of a C for loop variable after a for loop, simply because there is nothing special about a for loop variable in C.

      • It is simply a variable that has a scope defined by the block in which it is declared.
      • It must have been declared before it can be used in the for loop.
      • Any modifications made to it, either by the control statements or within the for loop body, persist after the for loop terminates, and until it goes out of scope.
      • It remains in scope, until the block it was defined in, ends.

      One all. Now lets get back to perl:)


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Hooray!

Re: Re: Re: Re: for loop localisation bug?
by Anonymous Monk on Dec 30, 2003 at 15:51 UTC
    Please don't use void main. It's broken, just like double main or union {int x; float y; } **main.

    The C standard says: main() must be declared as int main(void) or int main(int, char **) or equivalent (or in some implementation-defined manner, which is inherently unportable). See also http://users.aber.ac.uk/auj/voidmain.shtml.

      What can I say? It served its purpose. See you at SeaMonks.com for the follow-up:)


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Hooray!