C 为什么在循环内外声明同名的变量不会产生错误?

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); } } 这里的情况是,内在的我将遮蔽外在的我。根据其范围,这两个变量被视为

我有两个问题

为什么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);  
    }  
}  
这里的情况是,内在的我将遮蔽外在的我。根据其范围,这两个变量被视为独立变量

换句话说,在块内部范围内定义和显示的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