Consider this snippet of a C program:
for(int i = 0; i < 5; i++)
{
int i = 10; // <- Note the local variable
printf("%d", i);
}
It compiles without any error and, when executed, it gives the following output:
1010101010
But if I write a similar loop in C++:
for(int i = 0; i < 5; i++)
{
int i = 10;
std::cout << i;
}
The compilation fails with this error:
prog.cc:7:13: error: redeclaration of 'int i'
int i = 10;
^
prog.cc:5:13: note: 'int i' previously declared here
for(int i = 0; i < 5; i++)
^
Why is this happening?
This is because C and C++ languages have different rules about re-declaring variables in a scope nested in a for
loop:
C++
puts i
in the scope of loop's body, so the second int i = 10
is a redeclaration, which is prohibitedC
allows redeclaration in a scope within a for
loop; innermost variable "wins"Here is a demo of a running C program, and a C++ program failing to compile.
Opening a nested scope inside the body fixes the compile error (demo):
for (int i =0 ; i != 5 ; i++) {
{
int i = 10;
cout << i << endl;
}
}
Now i
in the for
header and int i = 10
are in different scopes, so the program is allowed to run.
Unlike C, C++ has the rule,
C++11-§6.5.3/1:
The
for
statementfor ( for-init-statement conditionopt ; expressionopt ) statementis 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 the condition [...]
This means that the scope of the for-init-statement
and the statement
are the same* and the code below will cause error
for(int i = 0; i < 5; i++){
int i = 10; // Invalid.
// ...
}
In C,
C11-§6.8.5/5:
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.
Therefore, statement
has it's own scope and the above code is valid and equivalent to
for(int i = 0; i < 5; i++){
{
int i = 10; // Valid.
// ...
}
}
Suggested reading: n3337: 6.5.1 The while statement/p(2). Same reference can be found in c++17 draft (n4659) in section § 9.5.1 and §9.5.3 .
It's not redeclaration.
See this carefully...
for(int i = 0; i < 7; i++)
{
printf("i = %d\n", i);
int i = 5;
printf("new i = %d\n", i);
}
Output of the above code:-
i = 0
new i = 5
i = 1
new i = 5
i = 2
new i = 5
i = 3
new i = 5
i = 4
new i = 5
i = 5
new i = 5
i = 6
new i = 5
Clearly, there are two different i
's
The newer i
has a more local scope.
Is it a bug?
No
What is the purpose?
If it wasn't allowed, it might be very hard to maintain large projects, as you would constantly run into naming collisions.
Generally though, it is considered very poor practice to give the same name to different variables in different scopes, you should avoid doing that whenever possible.
Why is there no warning message?
Use gcc file_name.c -Wshadow
to compile.
EDIT: You can also locally lock the originally declared variables by redeclaring them in for loops.
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