Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error redeclaring a for loop variable within the loop

Tags:

c++

c

for-loop

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?

like image 598
Ayush Singh Avatar asked May 01 '18 19:05

Ayush Singh


3 Answers

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 prohibited
  • C 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.

like image 61
Sergey Kalinichenko Avatar answered Nov 11 '22 23:11

Sergey Kalinichenko


Unlike C, C++ has the rule,
C++11-§6.5.3/1:

The for statement

for ( for-init-statement conditionopt ; expressionopt ) 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 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 .

like image 23
haccks Avatar answered Nov 11 '22 22:11

haccks


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.

like image 1
Sailesh010 Avatar answered Nov 11 '22 22:11

Sailesh010