C 为什么在循环内外声明同名的变量不会产生错误?
我有两个问题 为什么i没有重新声明错误? 为什么输出是10 5倍而不是10 1倍? 在代码中 int i;在外部块范围内。 int i=10;在for循环的内部块范围内 如果我们想象同样的情况,我们可以想出类似的C 为什么在循环内外声明同名的变量不会产生错误?,c,loops,for-loop,scope,C,Loops,For Loop,Scope,我有两个问题 为什么i没有重新声明错误? 为什么输出是10 5倍而不是10 1倍? 在代码中 int i;在外部块范围内。 int i=10;在for循环的内部块范围内 如果我们想象同样的情况,我们可以想出类似的 { int i; for(i=0;i<5;i++) { int i=10; printf("%d",i); } } 这里的情况是,内在的我将遮蔽外在的我。根据其范围,这两个变量被视为
{
int i;
for(i=0;i<5;i++)
{
int i=10;
printf("%d",i);
}
}
这里的情况是,内在的我将遮蔽外在的我。根据其范围,这两个变量被视为独立变量
换句话说,在块内部范围内定义和显示的i将比外部范围内的变量更优先。因此,内部i值将被打印
OTOH,循环计数器变量i保持在外部范围。它的值不会通过块内的赋值进行更改。因此,它正确地循环了5次
相关:根据C11标准第§6.2.1章第4段
…[…]。。如果标识符以相同的名称指定两个不同的实体
空间,范围可能重叠。如果是这样的话,一个实体的范围(内部范围)将在另一个实体的范围(外部范围)之前严格结束。在内部范围内,标识符指定在内部范围内声明的实体;在外部范围中声明的实体是隐藏的,在内部范围中不可见
所以,为了回答你的问题
为什么i没有重新声明错误
因为两个is被视为单独的变量,尽管它们的名称相同
为什么输出是10 5倍而不是10 1倍
因为用作计数器的外部i不会从循环内部更改,只有循环增量条件会更改该值。因为i'int i=10'的第二个声明在循环内部,所以您没有声明i。这意味着在您的示例中,对于循环的每次迭代,都会销毁并重新创建变量 在任何复合语句中创建的变量的范围仅限于复合语句本身 Ps:如果你想通过改变i的值来停止循环
{ //---------------------------|
int i; |
for(i=0;i<5;i++) |
{ |
int i=10; //-------| inner scope |> Outer scope
printf("%d",i); //-------| |
} |
} //----------------------------|
这一切都与标识符的范围有关。标识符只是C中实体对象、函数、typedef名称等的名称,根据C11 6.2.1/1:
同一标识符可以表示程序中不同点上的不同实体
实体的范围在该节的/2中描述:
对于标识符指定的每个不同实体,标识符是可见的,即只能在称为其范围的程序文本区域内使用
和/4涵盖您的具体情况:
如果标识符在同一名称空间中指定两个不同的实体,则作用域可能重叠。如果是这样的话,一个实体的范围(内部范围)将在另一个实体的范围(外部范围)之前严格结束
换句话说,类似于:
{
int i;
for(i=0;i<5;i++)
{
i=10;
printf("%d",i);
}
}
完全有效,将打印42 17 42。这是因为内部块中的标识符i在它自己的范围内,它在第一个右括号处结束
在您的特定情况下,您可以将其视为:
{
int i = 42;
printf ("%d ", i);
{
int i = 17;
printf ("%d ", i);
}
printf ("%d\n", i);
}
内部int i=10有效值在for循环体的持续时间内隐藏外部i。这就是为什么它会打印很多10而不是0..4
内部i的范围在for循环体的闭合括号处结束,这样,当检查for循环的继续条件时,它将再次看到外部i。这就是为什么它会循环五次而不是一次。如果您询问编译器gcc-Wshadow,它会警告您
{
int i; \
for(i=0;i<5;i++) > outer i scope
{ /
int i=10; \
printf("%d",i); > inner i scope
} /
}
Sourav,根据第3段,仅标签名称具有功能范围。int i是函数块的块作用域,就像int i=10是for块的块作用域一样。@paxdiablo先生,谢谢您指出这一点。修改答案,请复习一次:-@Eregrith:C的所有版本并不真正了解C89之前允许在块开头声明的情况。张贴的代码是有效的C89。@Eregrith您错了。OPs代码中的所有声明都在块的开头,正如C89所要求的那样。啊,是的,也许吧。我的错。
echo -e '#include <stdio.h>\nvoid f(void) { int i; for (i = 0; i < 5; i++) { int i = 10; printf("%d", i); } }' | gcc -Wshadow -xc -c -
<stdin>: In function 'f':
<stdin>:2:53: warning: declaration of 'i' shadows a previous local [-Wshadow]
<stdin>:2:20: note: shadowed declaration is here