在循环

时间:2018-05-01 19:23:03

标签: c++ c for-loop

考虑一下C程序的片段:

for(int i = 0; i < 5; i++)
{
    int i = 10;  // <- Note the local variable

    printf("%d", i); 
}    

它编译时没有任何错误,并且在执行时,它提供以下输出:

1010101010

但是如果我在C ++中写一个类似的循环:

for(int i = 0; i < 5; i++)
{
     int i = 10;

     std::cout << i; 
}

编译因此错误而失败:

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++)  
             ^   

为什么会这样?

3 个答案:

答案 0 :(得分:27)

这是因为C和C ++语言在嵌套在for循环中的范围内重新声明变量的规则不同:

  • C++i置于循环体的范围内,因此第二个int i = 10是重新声明,禁止使用
  • C允许在for循环内的范围内重新声明;最里面的变量&#34;胜利&#34;

以下是running C programC++ program failing to compile

的演示

在正文中打开嵌套作用域修复了编译错误(demo):

for (int i =0 ; i != 5 ; i++) {
    {
        int i = 10;
        cout << i << endl;
    }
}

现在i标题中的forint i = 10位于不同的范围内,因此允许该程序运行。

答案 1 :(得分:21)

与C不同,C ++有规则,
C ++ 11-§6.5.3/ 1:

  

for声明

for ( for-init-statement conditionopt ; expressionopt ) statement 
     

相当于

{
    for-init-statement 
    while ( condition ) {
        statement 
        expression ;
    } 
}
     

除了在 for-init-statement 中声明的名称与相同的声明区中的名称在条件[...]中声明的名称

这意味着for-init-statementstatement的范围是相同的 * ,下面的代码会导致错误

for(int i = 0; i < 5; i++){
     int i = 10;    // Invalid. 
     // ...
}

在C中,
C11-§6.8.5/ 5:

  

迭代语句是一个块,其范围是其封闭块范围的严格子集。 循环体也是一个块,其范围是迭代语句范围的严格子集

因此,statement拥有自己的范围,上述代码有效且等效于

for(int i = 0; i < 5; i++){
    {
         int i = 10;    // Valid. 
         // ...
    }
}

建议阅读:n3337:6.5.1 while语句/ p(2)。相同的参考资料可以在c ++ 17 draft(n4659)的第9.5.1节和第9.5.3节中找到。

答案 2 :(得分:1)

这不是重新声明。

请仔细阅读...

for(int i = 0; i < 7; i++)
{
    printf("i = %d\n", i);
    int i = 5;
    printf("new i = %d\n", i);
}

以上代码的输出:-

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

很明显,有两个不同的i

较新的i具有更广泛的本地范围。

这是一个错误吗?

目的是什么?

如果不允许这样做,则维护大型项目可能会非常困难,因为您会经常遇到命名冲突。

尽管通常来说,对不同范围内的不同变量使用相同的名称被认为是非常差的做法,但应尽可能避免这样做。

为什么没有警告消息?

使用gcc file_name.c -Wshadow进行编译。


编辑: 您还可以通过在for循环中重新声明原始声明的变量来本地锁定原始声明的变量。