In the C language, if we write this:
for(int i = 0; i < 7; i++)
{
// for loop Body
}
The scope of variable i
is inside the for loop body. It is OK.
But, if I write this:
for(int i = 0; i < 7; i++)
{
long int i = 1; // Redeclaration of i
}
Here, the variable i
is declared again inside the loop body, yet it successfully compiles and runs in C.
But, in C++, the compiler gives a "redeclaration of 'long int i'" error.
So, why doesn't the C compiler give a redeclaration error? Is it a compiler bug?
C++ and C make a distinction here. According to C11 (n1570) §6.8.5 ¶5, emphasis mine:
An iteration statement is a block whose scope is a strict subset of the scope of its enclosing block. The loop body is also a block whose scope is a strict subset of the scope of the iteration statement.
Which translates to this for a for loop:
{
declaration
while ( expression) {
statement
expression ;
}
}
Anything you put in the statement
part can hide whatever is introduced in the declaration. Now, C++(17, n4659) explicitly says something similar at [stmt.for]/1. But it also goes on to add:
except that names declared in the init-statement are in the same declarative region as those declared in the condition,
So here the second i
is indeed an attempt at a re-declaration. The above may sound confusing (names declared in the condidion!?), but the "condition" here is defined like this ([stmt.stmt]/1):
condition:
expression
attribute-specifier-seq decl-specifier-seq declarator brace-or-equal-initializer
It's that which allows while loops like this (C++ only):
while (T t = x) statement
And you may not re-declare t
inside the statement of the while loop.
Alternatively, the entire conclusion I reach is summarized in [stmt.iter]/3 (thank you @T.C.):
If a name introduced in an init-statement or for-range-declaration is redeclared in the outermost block of the substatement, the program is ill-formed.
First of all, there is no re-declaration inside the loop. Inside the loop body. i
is defined every time the loop is entered, and the scope is only till the loop body.
Once the loop finishes the iteration, the variable does not exist anymore. (First quote)
That being said, what you are seeing is a result of shadowing. (Second quote)
Quoting C11
,
If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. [...]
and,
[...] If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
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