{
int i;
for(i=0;i<5;i++)
{
int i=10;
printf("%d",i);
}
}
我有两个问题
i
没有重新声明错误?10
5次,而不是10
1次?答案 0 :(得分:4)
这一切都与标识符的范围有关。标识符只是在C中赋予实体(对象,函数,typedef名称等)的名称,并且根据C11 6.2.1 /1
:
相同的标识符可以表示程序中不同点的不同实体。
该部分的/2
中描述了实体的范围:
对于标识符指定的每个不同实体,标识符仅在称为其范围的程序文本区域内可见(即,可以使用)。
/4
涵盖了您的具体案例:
如果标识符指定同一名称空间中的两个不同实体,则范围可能会重叠。如果是这样,一个实体(内部范围)的范围将严格地在另一个实体(外部范围)的范围之前结束。
换句话说,比如:
{
int i = 42;
printf ("%d ", i);
{
int i = 17;
printf ("%d ", i);
}
printf ("%d\n", i);
}
完全有效,并会打印42 17 42
。那是因为内部块中的标识符i
位于其自己的范围内,该范围以第一个右括号结束。
在您的特定情况下,您可以将其视为:
{
int i; \
for(i=0;i<5;i++) > outer i scope
{ /
int i=10; \
printf("%d",i); > inner i scope
} /
}
内部int i=10
有效隐藏i
循环体的持续时间for
。这就是为什么它打印了很多10
而不是0..4
。
内部i
的范围在for
循环体的右括号处结束,这样,当检查for
循环的连续条件时,它再次看到外i
。这就是为什么它循环五次而不是一次。
答案 1 :(得分:1)
在您的代码中
int i;
位于外部区块范围内。int i=10;
位于for
循环如果我们想象一下,我们可以提出像'
这样的东西{ //---------------------------|
int i; |
for(i=0;i<5;i++) |
{ |
int i=10; //-------| inner scope |> Outer scope
printf("%d",i); //-------| |
} |
} //----------------------------|
这里的情况是,内部 i
阴影外部i
。这两个被视为单独变量(基于其范围)。
换句话说,块(内部范围)中定义和存在的i
将具有更多优先级(超出外部范围中的变量)。因此,内部i
值将被打印。
OTOH,循环计数器变量i
保留在外部范围。它的价值不会因为街区内的分配而改变。所以,正如所问的那样,它正好循环了5次。
相关:来自C11
标准,章节§6.2.1,第4段,
.. [..] .. 如果标识符指定同名的两个不同实体 空间,范围可能重叠。如果是这样,一个实体的范围(内部范围)将严格地在另一个实体(外部范围)的范围之前结束。在内部范围内,标识符指定在内部范围内声明的实体;在外部范围内声明的实体在内部范围内是隐藏(并且不可见)。
所以,回答你的问题,
为什么i没有重新声明错误?
因为两个i
被视为单独变量,尽管名称相同。
为什么输出将是
10
5次,而不是10
1次?
因为,用作计数器的外部i
不会从循环内部更改,只有循环增量条件才会改变该值。
答案 2 :(得分:0)
由于i的第二个声明(&#39; int i = 10&#39;)位于循环内,因此您不会重新声明我。这意味着在您的示例中,变量将被销毁并为循环的每次迭代重新创建。
在任何复合语句中创建的变量范围仅限于复合语句本身。
Ps:如果你想通过改变i
的值来停止循环{
int i;
for(i=0;i<5;i++)
{
i=10;
printf("%d",i);
}
}
答案 3 :(得分:0)
如果您很好地询问编译器(gcc -Wshadow
),它会发出警告
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