TITLE: scoping and nested for loops PROBLEM: Jim Melton I came upon the following code the other day: for (int i=0; i < a_max; i++) for (int j=0; j < b_max; j++) // do something for (i=0; i < c_max; i++) // NOTE 1 for (int j=0; j < d_max; j++) // Compiler complains here // do something else NOTE 1: I thought the scope of 'i' was limited to the first for-loop. I have seen compilers which allowed the re-declaration of 'i' here, but most recent ones do not. On my SGI (DCC) the compiler complained about the redeclaration of 'j' in the second loop. It seems to me that the scope of 'j' *must* not extend beyond the first 'i' loop, but the compiler didn't agree. Is this a compiler bug? {These scoping rules were added recently, and newer compilers support them. -mod} RESPONSE: kanze@gabi-soft.fr (J. Kanze), 6 Jun 96 The situation is a little more complicated than the moderator's comment would suggest. With regards to "i", the new rules have it going out of scope at the end of the for loop, whereas the old rules maintained it in scope until the end of the enclosing block. At least one version of g++ implemented the new rules by default, with a flag to revert to the old rules. I'm not sure, but I think that the current version has reverted to the old rules by default, with a flag to get the new rules. Presumably, the new rules broke so much code that g++ had to back down. (If I'm wrong about this, could someone from Cygnus correct me.) The situation with regards to "j" is more ambiguous. The new rules are simple, "j" goes out of scope at the end of the for in which it is declared. The old rules were never specified. While you could make a very good argument that "j" should go out of scope at the end of the for loop which contained it (the one with the "i"), many compilers did not do this, but left it in scope until the end of the block. This variant could easily be detected in CFront by replacing the int (type of "j") with a class type with a constructor and destructor. The constructor would be called once each time through the outer loop (and thus potentially 0 times, potentially many times); the destructor would be called once, at the end of the block, regardless of if or how many times the constructor was called. (Need I say that I considered such behavior a bug, not a feature. One could argue that it was required by a literal reading of the ARM, however.) Given the variety of behavior of existing compilers, I would strongly recommend inserting extra braces all over the place, to force scoping to what you want. Given the behavior of CFront (and the fact that many compilers took it as a reference, and did likewise), I would *always* use braces around a nested for.