Thread: Hammer, a question for you - var scope

  1. #1
    *
    Guest

    Hammer, a question for you - var scope

    Hammer,

    In another thread, I saw a response from you, about Salem's instructional code to someone else.

    Essentially, a variable was declare within a for() loop that had additional braces. You said:

    > That way the variable is only visible within the loop,
    > and not within the rest of the function. This is the
    > same for most variables created within braces

    Are you sure about this? Can you point me at a reference? Is this a C++ abstraction?

    I would be very surprised if that variable isn't accessible anywhere in the rest of the function, because it had to be allocated on the stack when the function was jumped to.

    Thanks

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    To save everyone searching for the thread, could you paste its link?

  3. #3
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    Well, try to compile this and watch the error messages you get:
    Code:
    int main()
    {
       for(int i = 0; i < 5; i++)
       {
          int MyVar = 5;
       }
       MyVar = 6;
    
       for(int LoopVar = 0; LoopVar < 5; LoopVar++)
       {
    
       }
       LoopVar = 6;
    
       return 0;
    }
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I would be very surprised if that variable isn't accessible
    >anywhere in the rest of the function
    A variable created inside a loop will not be accessable outside of that loop. Consider the following code:
    Code:
    #include <stdio.h>
    
    int main ( void )
    {
      int a;
      for ( a = 0; a < 5; a++ ) {
        int b = 0;
        b += a;
      }
      printf ( "%d\n", b );
      return 0;
    }
    The variable a is pushed onto the stack, the loop is entered and is treated as a new block, b is pushed onto the stack, the loop performs its iterations and exits. When the block is terminated, all variables declared in that block are popped from the stack, so the variable b is invalid when execution reaches the call to printf.

    >because it had to be allocated on the stack when the function was jumped to.
    But the loop is a separate block and thus a separate entity from the function which can declare its own automatic variables that are removed when the block returns. The same problem will occur if you throw out the loop and just use braces:
    Code:
    #include <stdio.h>
    
    int main ( void )
    {
      int a;
      {
        int b = 0;
        b += a;
      }
      printf ( "%d\n", b );
      return 0;
    }
    -Prelude
    My best code is written with the delete key.

  5. #5
    *
    Guest
    thanks everyone, I am going to try this and I will post back with what I find out. I will also let you know what compiler I'm using.

    I just find it irregular because stackframe size (of main()) is determined at compile time, not runtime.

    Again, I'll let you know what I find...

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > I just find it irregular because stackframe size (of main()) is determined at compile time, not runtime
    This seems to be true in the C case at least (using gcc here).

    Taking Prelude's examples, space for a and b will be allocated on the stack when the function is first called. b might exist for the entire life of the function, but its the language (at compile time) which enforces the scope rules, which determines where in the code it is permissible to access b. Whether b exists (or not) outside of its scope is a matter for the implementation.

  7. #7
    *
    Guest
    Okay, I tried the examples and here's what I found:

    Magos-- your example isn't even valid.

    Code:
    int main()
    {
       for(int i = 0; i < 5; i++)
       {
          int MyVar = 5;
       }
       MyVar = 6;
    
       for(int LoopVar = 0; LoopVar < 5; LoopVar++)
       {
    
       }
       LoopVar = 6;
    
       return 0;
    }
    You can't declare an 'int' in the middle of your loop. If your compiler allows it, it's a low-quality compiler.

    ------------

    Prelude-- Your first and second examples are invalid:

    Code:
    #include <stdio.h>
    
    int main ( void )
    {
      int a;
      for ( a = 0; a < 5; a++ ) {
        int b = 0;
        b += a;
      }
      printf ( "%d\n", b );
      return 0;
    }
    and

    Code:
    int main ( void )
    {
      int a;
      {
        int b = 0;
        b += a;
      }
      printf ( "%d\n", b );
      return 0;
    This code won't even compile in a professional grade 'C' compiler. If C++ would normally allow variable declarations this way, then it's because your implementation of a 'C' compiler happens to be generously allowing you to abstract where variables can be declared. This is not standard for 'C'.

    In otherwords, in C, the above examples are syntactically incorrect and break during symbol table build.

    ------

    I am using the latest version of C/C++ CodeWarrior, by MetroWerks. This compiler is used to build more software on every platform and game system than any other. It has become the defacto standard for the professional developer-- no i wasn't paid to say this (grin).

    I really wanted to be able to compile it and then post the dissassembly so we cold see where the vars were allocated and how they were being accessed-- but since it's syntactically incorrection, I couldn't get that far.

    Oh well.

  8. #8
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    Originally posted by *
    Okay, I tried the examples and here's what I found:

    Magos-- your example isn't even valid.
    If you take the time to read my post, you'll see that I wrote:
    Well, try to compile this and watch the error messages you get
    Which clearly states that the code is non-functional.
    And regarding int's being defined inside for-loops, it works fine on my compiler. If it doesn't work for you, it isn't hard to move the definition outside.
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  9. #9
    *
    Guest
    Magos-- sorry about that. I see your point now. I just felt (in the end) that the example you provided wasn't germaine if It wouldn't compile.

    If you can do this, fine, but me personally I would be leary of it. I think scattering variables loosely in code is a bad idea-- it makes their declaration hard to find in any sizeable work (say 300K of sourcecode over 40+ files).

  10. #10
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >In otherwords, in C, the above examples are syntactically
    >incorrect and break during symbol table build.
    Prove it. I don't have my copy of the C standard handy right now, but K&R2 explicitly states that:
    Declarations of variables (including initializations) may follow the left brace that introduces any compound statement, not just the one that begins a function. Variables declared in this way hide any identically named variables in outer blocks, and remain in existance until the matching right brace. For example, in
    Code:
    if (n > 0) {
        int i; /* declare a new i */
    
        for (i = 0; i < n; i++ )
            ...
    }
    It seems highly unlikely to me that such a broad reaching feature would be left out of the standard.

    >I think scattering variables loosely in code is a bad idea
    I agree, declaring variables at the beginning of a function only is my preferred method unless doing otherwise would result in some signifigant gain.

    -Prelude
    My best code is written with the delete key.

  11. #11
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    Originally posted by *
    If you can do this, fine, but me personally I would be leary of it. I think scattering variables loosely in code is a bad idea-- it makes their declaration hard to find in any sizeable work (say 300K of sourcecode over 40+ files).
    True! But in this case, we're talking about loop-variables.
    I usually put all my "normal" declarations in the beginning of a block, or at well thought-out places.

    In case of multiple for loops following each other, I declare a variables outside the for-loop so the loop can share the storage.
    Code:
    int i;
    
    for(i=0; i<5; i++) cout << i;
    for(i=3; i>1; i--) cout << i;
    for(i=-3; i<=0; i++) cout << i;
    But most of the time I put it inside. As far as I know, neither of the ways are right nor wrong. Depends on the compiler I suppose...
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  12. #12
    Me want cookie! Monster's Avatar
    Join Date
    Dec 2001
    Posts
    680
    Originally posted by Prelude
    Declarations of variables (including initializations) may follow the left brace that introduces any compound statement, not just the one that begins a function. Variables declared in this way hide any identically named variables in outer blocks, and remain in existance until the matching right brace.

    -Prelude
    That's really messy:
    Code:
    int main()
    {
      int i = 0;
      {
        int i = 1;
        {
          int i = 2;
          printf("%d\n", i);
        }
        printf("%d\n", i);
      }
      printf("%d\n", i);
    
      return 0;
    }

  13. #13
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    Cool, I didn't know that you could make blocks using { }.
    Code:
    #include <stdio.h>
    #include <conio.h>
    
    int i=4;
    
    int main()
    {
       {
          int i=5;
          {
             int i=8;
             printf("  i: %d\n::i: %d", i, ::i);
    
             {
                printf("\n  i: %d", i);
             }
          }
       }
       getch();
       return 0;
    }
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  14. #14
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >That's really messy:
    Messy, hard to read, but valid and sometimes useful. Provided you don't use the same names in nested blocks, that can get truly confusing.

    -Prelude
    My best code is written with the delete key.

  15. #15
    *
    Guest
    Well, it sounds like it is part of the standard, but is it part of the C standard or the C++ standard?

    It also sounds like it is highly compiler-dependent as to whether this feature is supported, which suggests to me that it is either esoteric, or of limited usefulness.

    Can anyone who actually _can_ compile the examples above, print out a dissassembly and post it? I'd like to see how the variables are allocated and initially referenced in assembly. Seemingly, to create additional layers of scope as this change adopts can only mean that the stackframe has to be larger than it otherwise would be, because although the variable names could be the same inside and outside of braces, separate data spaces must be allocated for each. Kinda foolish, I think.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. quick question about scope resolution
    By *ClownPimp* in forum C++ Programming
    Replies: 8
    Last Post: 11-03-2002, 10:04 PM
  2. what does this warningmean???
    By kreyes in forum C Programming
    Replies: 5
    Last Post: 03-04-2002, 07:53 AM
  3. Question about C# scope rules
    By converge in forum C# Programming
    Replies: 3
    Last Post: 01-30-2002, 06:56 AM
  4. Scope question
    By mikebrewsj in forum C++ Programming
    Replies: 1
    Last Post: 01-17-2002, 04:47 PM