rulururu

post Correctly implement for() loop scooping

June 2nd, 2008

Filed under: C++, Visual Studio — Kai @ 2:13 pm

The following code snipped gives an error when compiling it with VC6, although it’s legal according to the C++ standart.

SomeFunction ()
{
    for (int i =0; i<5; i++)
    { ... }
    for (int i =0; i<10;i++)
    { ... }
}

Previously, the definition would be considered occurring outside of the braces, and would be in scope until the end of the outer enclosing braces (until the end of SomeFuncion() in the example above), so defining i in the second for loop gives a redefinition error.
Under the new rules, the variable definition is considered occurring inside the braces of the for() loop, and it goes out of scope at the end of the for loop, so both variable definitions given above would be needed.

It gives an error on the second for () complaining about i being redefined.

  • In VC7 (2002), the compiler was changed so that both conforming and
    non-conforming code was accepted, but neither interpretation was enforced -
    you could freely mix.
  • In VC 7.1 (2003), the /Zc:forScope option was introduced and was by-default
    turned off, preserving the VC7 (and earlier) behavior.
  • In VC8 (2005), the default was changed so that the option is on by default.
  • VC9 (2008) changes nothing with regard to for-loop variable scoping.

So, what do you do if you need the new scooping rules?

A tumb rule is that you can turn it off, and get the VC6 behavior, by adding /Zc:forScope- to
your compiler options in the project properties dialog.

The following macro has been suggested as a workaround:

#define for  if (0) {} else for

However, using a macro to change the semantics of a program is generally not a good idea, and should only be used in extreme cases, such as when trying to compile code developed under a compiler that implements the new rule. Applying the macro to code developed under the original rule can result in silent behavioral changes, as described above. A compiler that implements the new rule can warn about code whose interpretation differs under the old and new rules, so it’s best to wait for proper compiler support, if you can.

Another way you can go is to use the preprocessor macro MSC_VER and create conditional compilation blocks, or simply define the varibable outside of the first loop and set initialize it every time again.

Yet another workaround is to enclose each for() sentence in braces, like this:

{
    for ( int i = 0; i < 10; i++ )
    {
        //  ...
    }
}
{
    for ( int i = 0; i < 12; i++ )
    {
        //  ...
    }
}

This effectively creates yet another scope that hides the for-loop scooping bug. However, it adds unnecessary scopes and is easy to forget to close one of them or them alltogether.

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

ruldrurd
Powered by WordPress, Content and Design by Kai Bellmann
Entries (RSS) and Comments (RSS)