Thread: Declaration inside for statement - scope according to the standard

  1. #1
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788

    Declaration inside for statement - scope according to the standard

    If we declare variable inside for() what is the scope of it according to the last standard of the C++?

    Code:
    int main()
    {
    	int i; //is it in the same skop as i1?
    	for(int i1 = 5; i;--i) 
    	{
    		int i2; //is this 3rd skop? it is possible to declare local int i1 here?
    		//...
    	}
    	//is i1 visible here?
    }
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    i is outside the for scope, but visible.
    i1 is destroyed after '}', along with i2.
    i1 and i2 share the same scope.

    In other words, the for loop, along with while, if, else, and switch, all introduce a new scope.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    i1 is only in the scope of the for loop, as is i2, thus i1 is not visible after the for loop. i's scope extends beyond the for loop.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    so the code
    Code:
    for(int i = 5; i;--i) 
    {
    	int i;
    	//...
    }
    contains error?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Yup. That would be a re-definition generating a compile time error, since i is already in scope from the for header.

    However, since the for loop introduces a scope, rules for nested scopes take place too. So...

    Code:
    int i;
    
    for (int i1;;++i) {
        int i;
    }
    Does not incur in a compile time error. The for loop defines its own nested scope. i is created inside the nested scope, effectively shadowing the higher-scoped i. Any changes to i inside the for loop, will only affect that inner variable. Once the for loop is finished, the higher-scoped i becomes visible again.

    Code:
    int a;
    
    {
        a = 13; // the higher-scoped a is assigned 13;
    
        int a;  // new a, shadowing the former one.
    
        a = 23;  // only the inner a is affected
    }
    
    std::cout << a;  // outputs 13
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Thanks for the answers. My knoledge here was a little bit outdated. Now it is fixed...
    Thanks againg.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Note that older compilers do not support the standard in this area very well, most notable VC++ 6.0.

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    This I know, that's why instead of checking on my compilers I have asked the question here...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  9. #9
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Pre-standard C++, i1 would generally have the same scope as i.

    Since the 1998 standard, i1 is required to have the same scope as i2.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I don't have the standard, but it seems to me that the below program has actually three scopes: one that lasts during the main function, one that lasts the lifetime of the for loop itself, and one between the brackets of the loop. The innermost i is declared and goes out of scope with each iteration, the loop counter i lasts the "lifetime" of the whole loop.

    (It's important to know thy scopes, of course, not how to misname the variables.)

    Code:
    #include <iostream>
    
    int main()
    {
        int i = 42;
        for (int i = 0; i < 10; i++){
            std::cout << "Counter::i " << i << std::endl;
            int i = 999;
            std::cout << "Loop::i " << i << std::endl;
        }
        std::cout << "Main::i " << i << std::endl;
        std::cin.get();
    }
    Last edited by anon; 11-28-2006 at 02:46 PM.

  11. #11
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    > one that lasts during the main function, one that lasts the lifetime of the for loop itself, and one between the brackets of the loop.

    Not really. Your code won't compile on a standards compliant browser. The init-statement in the for header introduces a name into the for statement scope (a new nested scope introduced by the for statement). It will shadow the i defined in main and will be destroyed when the for loop finishes.

    The i defined inside the for loop will clash with the same definition on the for header and generate an ODR compile-time error. They are on the same scope.

    Note that the curly-braces are not necessarily a physical indication of when the scope is created. The following code doesn't even have curly braces and will still generate a compile-time error.

    Code:
    int main() {
        
        if (true)
            int i = 13;
    
        ++i;
    
    }
    EDIT: Wow... I'm wrong. You are right anon. The for statement introduces two scopes. One in the header, another in the body. I was totally unaware of that
    Last edited by Mario F.; 11-28-2006 at 02:56 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  12. #12
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The i defined inside the for loop will clash with the same definition on the for header and generate an ODR compile-time error. They are on the same scope.
    While it's going to be hard arguing with someone who's probably read the standard (I haven't) , common sense tells me that this cannot be so. If it were so, you shouldn't be able to declare any names inside a loop (its curly brackets). If that variable didn't go out of scope at the end of the iteration, I can't see how that would be different from
    Code:
    int main() {
        int i = 0;
        int i = 0;
        //redeclare i as many times as the loop would do it.
    }
    Now, that does produce a "redeclaration" error.

  13. #13
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    > While it's going to be hard arguing with someone who's probably read the standard

    I'm actually baffled because you shown me something new

    > common sense tells me that this cannot be so. If it were so, you shouldn't be able to declare any names inside a loop (its curly brackets).

    Why's that? The for loop introduces a new scope (let's for the sake of argumentation assume it starts right at the for keyword). This new scope is nested. It follows the same rules as any other nested scope. Identifiers can be introduced, if their names are the same as any declarations on an higher scope in the hierarchy, the will shadow those names. Try my code on this thread with the variable a, some posts above.

    However... back to the hot potato (the for statement)...

    The standard states this in 6.5.3.3
    If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for-statement.
    Just to clarify, the standard also (obviously) defines the for statement:
    Quote Originally Posted by 6.5.3.1
    for ( for-init-statement ; condition ; expression ) statement
    So from this alone, one would assume no way I could define i both in the init-statement and the statement

    But with these things we are better if we read veeery slowly and veery carefully

    This is the remaining of 6.5.3.1:
    The for statement

    for ( for-init-statement condition ; expression ) statement

    is equivalent to

    Code:
    { <--- aha!
        for-init-statement
        while ( condition ) { <--- aha!
            statement
            expression ;
       }
    }
    except that names declared in the for-init-statement are in the same declarative-region as those declared in the condition, and except that a continue in statement (not enclosed in another iteration statement) will execute expression before re-evaluating condition.
    And so it is, two scopes per for loop. I never noticed that before. So you are right. It is possible (and standard) to shadow the init-statement identifier
    Last edited by Mario F.; 11-28-2006 at 03:50 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  14. #14
    MFC killed my cat! manutd's Avatar
    Join Date
    Sep 2006
    Location
    Boston, Massachusetts
    Posts
    870
    Wow thanks for that. I always assumed the same as Mario F. Always learning
    Silence is better than unmeaning words.
    - Pythagoras
    My blog

  15. #15
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Actually, that makes sense now, especially when thinking about what anon said.

    An object declared inside the body of the loop will be constructed and destructed every iteration through the loop; an object declared inside the initializer will be constructed before the loop and destructed immediately after.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. variables when declared inside or outside a function
    By jas_atwal in forum C Programming
    Replies: 6
    Last Post: 12-14-2007, 02:42 PM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Still battling with Copy Control
    By Mario F. in forum C++ Programming
    Replies: 9
    Last Post: 06-23-2006, 08:04 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Using c++ standards
    By subdene in forum C++ Programming
    Replies: 4
    Last Post: 06-06-2002, 09:15 AM