C++ – for loops
I am [mostly] a fan of using C++ for embedded applications. I believe its use needs care and I have written about this before. Broadly, I feel that it offers many simple improvements over C and appropriate use of object oriented techniques can be very beneficial. Today I want to talk about the place of C++ as a “better C language”. There are numerous syntactical improvements that can be leveraged to make code just a little more readable and maintainable.
However, there are some minor “quirks” that can catch the unwary programmer. Who would have thought that you could go wrong with a plain old for loop? …
In C, it might be very common to write code that looks like this:
int i, j; ... ... for (i=0; ... ... for (j=0; ...
Nothing complex or strange about that. A smart programmer might choose to use the same loop incrementing variable, i, for both for loops, as they are mutually exclusive and this might save memory, stack space or, most likely, a register. However a modern compiler would probably use “register coloring” optimization and use the same register for both i and j.
The only issue with this code is that the declaration of i and j are right at the beginning of the function – far removed from their usage. At a glance, it is impossible to be certain about exactly where they are used and what the implications of a change might be. The best you can really do is comment the declaration as clearly as possible and hope that someone modifying the code in the future reads the comments and updates them to accommodate any changes.
C++ gives much more flexibility in the location of variable declarations. So, you can write a for loop thus:
for (int i=0; ...
This is much nicer, but unfortunately can cause a problem. If you code another for loop later in the same function and choose to use the same name for loop iteration variable, you will most likely get an error from the compiler complaining about the redefinition of i [which is not legal in C++].
Why does this error occur? The reason is clear if you consider the implementation of a for loop. This code:
for (int i=0; i<3; i++) x[i] = i;
can be recoded thus:
int i=0; while (i<3) { x[i] = i; i++; }
It is now clear that the declaration of i renders the variable in scope for the rest of the function. This could be fixed, if the for loop were expanded like this:
{ int i=0; while (i<3) { x[i] = i; i++; } }
I am sure that many modern compilers do just this, but I have found that this was not always the case, so care with code portability is needed.
But according to the C++ standard, the scope of i only extends to the end of for statement. So if the compiler reports an error about that, it’s a bug of the compiler.
It is good news that this functionality has been standardized. However, deviations from language standards are not uncommon in C++ compilers.
This has been in the standard since at least 1998 (ISO/IEC 14882:1998 section 6.5.3). If I remember correctly, prior to 1998 this was not the case. So, to run into this problem today, you would either have to be using a really old compiler, or it is simply a bug.