在while循环中的变量声明 C/C++

4
根据我的理解,下面的while循环应该是无限循环,但实际上只运行了三次。
   main()
   {
   int i=3;       
   while(i--)
    {
      int i=100;
      i--;
      printf("%d..",i);
    }
   }

它输出99..99..99

但根据我的理解,由于每次控制进入while循环时都会得到值100,因此它应该无限运行。所以它永远不会达到零。 只是为了试验,我在while循环内部用i=100;替换了int i=100;,现在它无限运行..为什么???


感谢您的回答。我曾认为所有同名变量只存储单个值,并且仅在函数和声明中是局部的。 - Yadnesh
1
这个技术术语叫做“影子”:你在while循环之前定义的i被遮盖了。 gcc可以通过-Wshadow进行警告。 - pmg
5个回答

8

检查条件的变量i是您在main()中声明的变量,而不是循环内部的变量。

这两个变量是不同的,您将它们混淆为一个变量,但编译器并不像您那样容易混淆。

在循环内部,i指的是您在{}内部声明的变量,但在{}外部,i指的是在main()中声明的变量。


这是否意味着它们是两个不同的变量? - Yadnesh
@Yadnesh:是的,它们是。请查看我的答案。 - Alok Save

7
while(i--) 中的变量 i 与循环内定义的变量 i 是不同的。
基本上,int i = 100 “掩盖” 了先前的 int i = 3,并且在 while 块内部,你正在引用一个新变量。
总之,我找不到任何合理的情况需要这样做。

这是说它们是两个不同的变量吗? - Yadnesh
@Yadnesh 完全不同。 - cnicutar
变量通常不会有意地被遮蔽。这更多是为了方便,以防止全局命名空间污染本地命名空间。 - William Pursell

5
while(i--)
    {
      int i=100; // gets created every time the loop is entered
      i--;
      printf("%d..",i);
    } // the i in the loop keeps getting destroyed here

为什么不试试以下内容:

while(i--)
{

              {
                  int i=100; //Visible only in this scope
                  i--;
                  printf("inner i=%d..",i);
              } //gets destroyed here
        printf("\nouter i=%d..\n",i);
}

3

每个变量都指向其最近的声明(当然是在该作用域内有效的):

main()
{
   int i=3;       
   while(i--)             // this i is the one defined in the line above
   {
       int i=100;
       i--;               // this i is the one defined in the line above
       printf("%d..",i);  // this i is the one defined two lines above
   }
}

所以你的 while 循环会迭代 3 次,因为它依赖于由 int i = 3; 声明的 i。在循环内部,它打印出 99,因为其中的 i 指的是由 int i = 100; 声明的 i,它被 -- 了。

如果你将 int i = 100; 改为 i = 100,那么你就改变了第一个 i,而不是引入另一个变量。因此会导致无限循环。

编辑 有些人说,应该用“当前范围内可访问的最内层声明”代替“最近的”,并给出以下示例:

int a=4;
{
    int a=10;
}
printf("%d", a);

由于第二个a对于printf不可见,很明显printf("%d", a);无法引用它。我假设读者知道变量只能在其定义的范围内访问。否则,是的,前两个评论中的短语更加精确。


准确来说,不是“最近的”,而是“在最局部的范围内”。 - Karl Knechtel
我不会说“最近的”(像一些脚本语言中那样),而是指当前作用域内可访问的最内部声明(例如:int a=4; { int a=10;} printf("%d", a); 输出的是4,而不是10)。 - Matteo Italia
2
“Most recent” 在技术上是非常准确的,但它要求你理解所有不同变量何时被创建。很可能,如果你已经理解了这一点,你就不需要这个规则了。 - David Schwartz
由于这让人们感到困惑,我将对其进行一些编辑。 - Shahbaz

1

C++中的每个作用域(粗略地说,每一对大括号,除了用于特殊目的如数组初始化)都可以包含自己的局部变量声明。在循环内部写入 int i = 100; 指定了另一个名为 i 的变量,该变量与循环外部的变量不同,并且默认情况下,使用 i 的作用域内的代码将引用内部的 i 而不是外部的 i。但是,循环条件中的 i-- 仍然使用外部的 i

当您用 i = 100 替换 int i = 100 时,现在只有一个变量,它被设置为100,递减两次(一次在循环内部,一次由循环本身递减),并再次设置为100,重复进行。


不,循环体中的 i-- 会递减内部的 i,而 printf 会打印内部的 i。外部的 i 在循环体的作用域内是不可见的。 - William Pursell
抱歉,不是循环体,是循环条件。我会修复的。 - Karl Knechtel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接