考虑一下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++)
^
为什么会这样?
答案 0 :(得分:27)
这是因为C和C ++语言在嵌套在for
循环中的范围内重新声明变量的规则不同:
C++
将i
置于循环体的范围内,因此第二个int i = 10
是重新声明,禁止使用C
允许在for
循环内的范围内重新声明;最里面的变量&#34;胜利&#34; 以下是running C program和C++ program failing to compile。
的演示在正文中打开嵌套作用域修复了编译错误(demo):
for (int i =0 ; i != 5 ; i++) {
{
int i = 10;
cout << i << endl;
}
}
现在i
标题中的for
和int 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-statement
和statement
的范围是相同的 * ,下面的代码会导致错误
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循环中重新声明原始声明的变量来本地锁定原始声明的变量。