Thread: Additional scope used with for loop/initializer variable when not using C99?

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    101

    Additional scope used with for loop/initializer variable when not using C99?

    You can do this in C99:

    Code:
    for(int i=0;i<100;i++){
    
    }
    But what if I'm not writing C99 code and want to keep the same behavior? Couldn't I just do this:

    Code:
    {int i;
    for(int i=0;i<100;i++){
    
    }}
    That way, if I have for loops later in the code I don't have to worry about the fact that I already declared i as an int. I might want to declare it as another type later.

    Is this a bad idea?

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    I assume that you mean the second example to be
    Code:
    {int i;
    for(i=0;i<100;i++){
     
    }}
    (Note that I removed the "int" from the for.)

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Quote Originally Posted by oogabooga View Post
    I assume that you mean the second example to be
    Code:
    {int i;
    for(i=0;i<100;i++){
     
    }}
    (Note that I removed the "int" from the for.)
    Yes, my mistake. Thanks.

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    To answer your question, I don't see anything technically wrong with doing that, but it isn't a common practice.

  5. #5
    Registered User
    Join Date
    Jun 2009
    Posts
    101
    Quote Originally Posted by oogabooga View Post
    To answer your question, I don't see anything technically wrong with doing that, but it isn't a common practice.
    I know, that's why I thought it might be good to ask. I guess this isn't a problem if declaring i at the top of the function (which, I think, you're supposed to to in ANSI C), but if you have a few loops throughout and only need i for the duration of the loop, this seems like a safe alternative to the C99 way.

  6. #6
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Then can I ask, what's gnu99? I compile with -std=gnu99. Is it logically equivalent to c99?

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by MutantJohn View Post
    Then can I ask, what's gnu99? I compile with -std=gnu99. Is it logically equivalent to c99?
    It is C99 with GNU extensions.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  8. #8
    Registered User
    Join Date
    Jun 2013
    Posts
    66
    Quote Originally Posted by oogabooga View Post
    To answer your question, I don't see anything technically wrong with doing that, but it isn't a common practice.
    Which of course raises the question of whether mixing declarations and statements in C99 is a valuable feature in the first place, or if it's nothing more than fluffy pandering to C++ programmers who can't handle writing disciplined C.

    Quote Originally Posted by synthetix View Post
    I guess this isn't a problem if declaring i at the top of the function (which, I think, you're supposed to to in ANSI C), but if you have a few loops throughout and only need i for the duration of the loop, this seems like a safe alternative to the C99 way.
    The requirement prior to C99 is that declarations come before executable statements in the block. This means that you do not need to place all declarations at the top of the function if a nested block works just as well. In fact, it's better practice to place variable declarations as close to their use as possible. This is the rationale for the C99 feature of mixing declarations and statements. But if the block is so long and messy that placing declarations at the top isn't adequate enough, mixing declarations and statements won't fix the real problem of poorly structured code.

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    ANSI C is ambiguous, since technically C89 (C90), C99, and C11 are all ANSI standards. The prior defacto standard is K&R C, but it's ancient history.

    The reason that declarations must go prior to statements in C89 is that in assembler, you want to reserve space for all stack variables at the start of the function, so the requirement helps compiler writers write simpler compilers. Clearly the C committee did not think that was sufficient reason to keep the feature in the years just prior to 1999.
    Last edited by King Mir; 06-23-2013 at 09:08 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  10. #10
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Actually C89 is an ANSI standard, C90, C99, and C11 are ISO standards.

    Jim

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Actually C89 is an ANSI standard, C90, C99, and C11 are ISO standards.
    O_o

    If you are going to be that picky, you are just as wrong; Standard C is a joint "ISO"/"IEC" standard.

    In reality, C90 and C99 are indeed "ANSI" standards, ISO standards, and $(OTHER STANDARD BODY) standards. (The C11 standard will likely be adopted entirely by "ANSI".)

    [Edit]
    Just a "heads up": if a lesser body has adopted the same "ISO" standard, it can often be found cheaper than from "ISO" proper.
    [/Edit]

    I don't know why people still don't get this concept after all this time.

    There are many standards bodies in the world.

    Sometimes a national or other lesser standard body will establish a standard first--as in C89.

    Sometimes the "International Standards Organization" will establish a standard first--as in C99.

    For the most part, lesser standard bodies will adopt "ISO" standards with no change or minor changes--as in C99.

    As often as not, the "ISO" will adopt established standards from lesser bodies, but sometimes changes are necessary for the sake of the international standard.

    Soma
    Last edited by phantomotap; 06-23-2013 at 10:05 PM.

  12. #12
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    I did not know that C11 wasn't adopted by ANSI. Learned something new today.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  13. #13
    Registered User ledow's Avatar
    Join Date
    Dec 2011
    Posts
    435
    Notice that if you compile with -Wshadow (on gcc, or whatever equivalent), your second code will produce a warning about the variable i being "shadowed", if there is another i in the blocks above it. This isn't a problem, but you just have to be careful with using "i" inside one of those blocks which, as the code gets larger and more complex, may well see you inadvertently using the for-loop variable instead of the slightly-more-global outer-block loop variable that you intended.

    Thus, nesting another block like this is something to be wary of, but yes, basically equivalent. But is it really that much harder than just declaring the variable at the beginning? And do you really want to risk having two "i's" in nested blocks?

    Personally, I declare where I first realise a variable is required. If it turns out to be confusing, conflicting or in any way sub-optimal, I move the declaration AND rename as necessary. You don't get performance gains from declaring variables earlier or later, just readability. And in modern UI's, the most readable way, I find, is to have declarations in a single block at the top of the functions so that readers can "skip" them while skimming, and yet know exactly where to find the definitions if they need them. Thus, I even tend to do:

    Code:
    int i;
    for(i = 0; i < LIMIT; i++)
    {
    ...
    };
    first (obviously compiles only as C99), then just shift the int i to the top of the block if required (i.e. moving to a non-C99 compiler, or to group declarations, etc.). I find the "in the for loop initialiser" declaration to be unnecessarily obscured when you're looking for declarations, and to be more difficult to cut/paste first time when you want to move it to the top of the block. But, as you can probably guess, that's more to do with ease of code management and saving myself a mis-click than any huge technical obstacle.

    Sticking to strict C-89 style declarations solves the problem all round and works for everyone. Using C99-style declarations is convenient for the programmer only, not for anyone who reads the code later or is running on an older standard compiler. You solve one problem (where's the declaration for i?), which can be easily resolved in any modern UI, by replacing it with something that introduces other problems. But in the grand scheme of things, none of it matters much and it's all down to personal style.

    - Compiler warnings are like "Bridge Out Ahead" warnings. DON'T just ignore them.
    - A compiler error is something SO stupid that the compiler genuinely can't carry on with its job. A compiler warning is the compiler saying "Well, that's bloody stupid but if you WANT to ignore me..." and carrying on.
    - The best debugging tool in the world is a bunch of printf()'s for everything important around the bits you think might be wrong.

  14. #14
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    You generally do want different loop indexes for nested loops, but using the C99 syntax can prevent related bugs. For instance:
    Code:
    for(int i=0;i<length;++i) {
      struct Example *container_of_stuff = do_stuff(i);
      for(int i=0;i<length_of_stuff;++i)
         use(container_of_stuff[i]);/*benign shadowing*/
      do_more_stuff(i) /*uses outer loop i, as intended*/
    }
    Putting the extra set of curly braces achieves the same thing, but it's not a common practice, so is likely to be forgotten.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 01-10-2012, 01:30 PM
  2. Replies: 8
    Last Post: 02-14-2010, 04:14 PM
  3. Variable Scope
    By Matty_Alan in forum C Programming
    Replies: 3
    Last Post: 11-23-2008, 03:28 PM
  4. Segfault with additional variable?
    By misterFry in forum C++ Programming
    Replies: 11
    Last Post: 11-12-2008, 10:55 AM
  5. Variable Scope
    By tinkerbell20 in forum C++ Programming
    Replies: 5
    Last Post: 06-22-2005, 10:31 PM