Error redeclaring a for loop variable within the l

2020-02-06 04:51发布

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?

标签: c++ c for-loop
3条回答
你好瞎i
2楼-- · 2020-02-06 05:29

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.

查看更多
走好不送
3楼-- · 2020-02-06 05:29

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 .

查看更多
男人必须洒脱
4楼-- · 2020-02-06 05:37

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.

查看更多
登录 后发表回答