When trying to compile the following (simplified) code for multiple platforms, I found that it was failing on some, namely IBM's xlC_r. Further investigation has found that it also fails on comeau and clang. It compiles successfully with g++ and Solaris's CC.
Here is the code:
int main()
{
int a1[1];
bool a2[1];
for (int *it = a1, *end = a1+1; it != end; ++it) {
//...
bool *jt = a2, *end = a2+1;
//...
}
}
xlC_r error:
"main.cpp", line 8.25: 1540-0400 (S) "end" has a conflicting declaration.
"main.cpp", line 6.25: 1540-0425 (I) "end" is defined on line 6 of "main.cpp".
clang error:
main.cpp:8:25: error: redefinition of 'end' with a different type
bool *jt = a2, *end = a2+1;
^
main.cpp:6:25: note: previous definition is here
for (int *it = a1, *end = a1+1; it != end; ++it) {
^
comeau error:
"ComeauTest.c", line 8: error: "end", declared in for-loop initialization, may not
be redeclared in this scope
bool *jt = a2, *end = a2+1;
^
The question is why is this an error?
Looking through the 2003 standard, it says the following (6.5.3):
The for statement
for ( for-init-statement; condition; expression ) statement
is equivalent to
{
for-init-statement;
while ( condition ) {
statement;
expression;
}
}
except that names declared in the for-init-statement are in the same
declarative-region as those declared in condition
Here there are no names declared in condition.
Further, it says (6.5.1):
When the condition of a while statement is a declaration, the scope
of the variable that is declared extends from its point of declaration
(3.3.1) to the end of the while statement. A while statement of the form
while (T t = x) statement
is equivalent to
label:
{
T t = x;
if (t) {
statement;
goto label;
}
}
Again, I'm not sure this is relevant, as there is no declaration in the condition. So given the equivalent re-write from 6.5.3, my code should be the same as:
int main()
{
int a1[1];
bool a2[1];
{
int *it = a1, *end = a1+1;
while (it != end) {
//...
bool *jt = a2, *end = a2+1;
//...
++it;
}
}
}
Which obviously would allow end to be re-declared.
Syntax. The init step is executed first, and only once. This step allows you to declare and initialize any loop control variables.
Declare the variables outside the loops. When you declare them inside the loop, they go out of scope as soon as the loop ends. You can't "call" a variable.
Yes, I can declare multiple variables in a for-loop. And you, too, can now declare multiple variables, in a for-loop, as follows: Just separate the multiple variables in the initialization statement with commas. Do not forget to end the complete initialization statement with a semicolon.
In computer programming, a loop variable is a variable that is set in order to execute some iterations of a "for" loop or other live structure. A loop variable is a classical fixture in programming that helps computers to handle repeated instructions.
The standard is somewhat ambiguous. The code you quote as being equivalent to a while
loop implies that there is an inner scope where declarations inside the loop could hide declarations in the condition; however the standard also says (quoting C++11, since I don't have C++03 handy):
6.4/2 The rules for conditions apply both to selection-statements and to the
for
andwhile
statements6.4/3 If the name is re-declared in the outermost block of a substatement controlled by the condition, the declaration that re-declares the name is ill-formed.
6.5.3/1 names declared in the for-init-statement are in the same declarative-region as those declared in the condition
which between them imply that the names can't be redeclared.
Older (pre-1998) versions of the language put declarations in the for-init-statement into the declarative region outside the loop. This meant that your code would be valid, but this wouldn't:
for (int i = ...; ...; ...) {...}
for (int i = ...; ...; ...) {...} // error: redeclaration of i
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With