在循环中重新声明for循环变量时出错

考虑一下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++) ^ 

为什么会这样?

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

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

这是一个正在运行的C程序的演示,以及一个无法编译的C ++程序 。

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

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

现在ifor header和int i = 10都在不同的范围内,所以允许程序运行。

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

for语句

  for(for-init-statement condition opt ; expression opt )语句 

相当于

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

除了在for-init语句中声明的名称与条件[…]中声明的名称相同的声明区域

这意味着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)。 可以在第9.5.1节和第9.5.3节中的c ++ 17 draft(n4659)中找到相同的参考。

这不是重新声明。

仔细看看……

 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有一个更局部的范围。

这是一个错误吗?

没有

什么目的?

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

但一般来说,在不同的范围内为不同的变量赋予相同的名称被认为是非常糟糕的做法,你应该尽可能避免这样做。

为什么没有警告信息?

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


编辑: 您也可以通过在for循环中重新声明它们来本地锁定最初声明的变量。