如果我在C语言的for循环中声明一个变量,它会被创建多次吗?

jjhzyzn0  于 2023-01-04  发布在  其他
关注(0)|答案(4)|浏览(409)
#include <stdio.h>

int main()
{
    for(int i=0;i<100;i++)
    {
        int count=0;
        printf("%d ",++count);
    }
    return 0;
}

上述程序的输出为:一一一一一一
请看一下上面的代码。我在for循环中声明了变量“int count=0”。据我所知,变量的作用域在块内,所以count变量将在for循环执行之前一直有效。“int count=0”执行了100次,那么它必须创建变量100次,否则它必须给予错误(重新声明计数变量),但它不是这样发生的-可能是什么原因?
根据输出,变量每次初始化为零。
请帮我找出原因。

6mw9ycah

6mw9ycah1#

这样简单的代码可以在http://www.pythontutor.com/c.html上可视化,便于理解。
回答你的问题,count在超出作用域时被销毁,也就是循环的结束}。在下一次迭代中,创建一个同名变量并初始化为0,由printf使用。
如果计数是您的目标,请打印i而不是count

7eumitmz

7eumitmz2#

C标准使用计算机的抽象模型来描述C语言。在这个模型中,count在每次执行循环的主体时被创建,并且在主体的执行结束时被销毁。通过“创建”和“销毁”,我们意味着为它保留内存并且释放内存,并且使用该保留来执行初始化。
C标准并不要求编译器盲目地实现这个模型,大多数编译器在例程开始时会分配一个固定数量的堆栈空间,count的空间包含在这个固定数量中,然后count在每次迭代中都使用这个相同的空间,然后,如果我们查看生成的汇编代码,我们将不会看到任何内存的保留或释放;对于整个例程,堆栈将仅增长和收缩一次,而不是在每次循环迭代中增长和收缩。
因此,答案是双重的:

  • 在C的抽象计算模型中,count的新生命周期在每次循环迭代中开始和结束。
  • 在大多数实际实现中,内存只为count保留一次,尽管实现也可以在每次迭代中分配和释放内存。

然而,即使你知道你的C实现在可能的情况下只为每个例程分配一次堆栈空间,你也应该从这方面考虑C模型中的程序。

for (int i = 0; i < 100; ++i)
{
    int count = 0;
    // Do some things with count.
    float x = 0;
    // Do some things with x.
}

在这段代码中,编译器可能会分配4个字节的堆栈空间给**countx使用,一次只给其中一个使用。例程在启动时将堆栈增长一次,包括用于countx的4个字节。在循环的每次迭代中,它将首先为count使用内存,然后为x使用内存。这让我们看到内存首先为count保留,然后释放,然后为x保留,然后释放,然后在每次迭代中重复。保留和释放在概念上发生,即使没有指令来增长和收缩堆栈。
另一个有启发性的例子是:

for (int i = 0; i < 100; ++i)
{
    extern int baz(void);
    int a[baz()], b[baz()];

    extern void bar(void *, void *);
    bar(a, b);
}

在这种情况下,编译器无法在例程启动时为ab保留内存,因为它不知道它需要多少内存。在每次迭代中,它必须调用baz以确定a需要多少内存以及b需要多少内存,然后必须分配堆栈空间(或其它存储器)。此外,由于大小可随迭代而变化,ab不可能在每次迭代中都在同一位置开始它们中的一个必须移动以便为另一个让路。因此,这段代码让我们看到,必须在每次迭代中创建一个新的a和一个新的b

af7jpaap

af7jpaap3#

int count=0执行100次,则必须创建变量100次
不,它 * 定义 * 变量count一次,然后 * 赋予 * 它值0 100次。

  • 在C语言中定义一个变量并不涉及任何特定的步骤或代码来“创建”它(不像在C++中,简单地定义一个变量可能会默认构造它)。变量定义只是将名称与一个在内部表示变量的“实体”相关联,并且定义与它们出现的范围相关联。
  • 赋值变量是在正常程序流程中执行的语句。它通常有“可观察到的效果”,否则编译器可以完全优化它。

OP的示例可以重写为完全等效的形式,如下所示。

for(int i=0;i<100;i++)
{
    int count;  // definition of variable count   - defined once in this {} scope
    count=0;    // assignment of value 0 to count - executed once per iteration, 100 times total

    printf("%d ",++count);
}
9jyewag0

9jyewag04#

Eric是正确的。在更短的形式:
通常计算机在编译时决定一个函数需要多少内存以及变量在堆栈中的位置。堆栈内存没有单独的分配/释放。
此外,当变量嵌套在{大括号}中时,一旦执行离开了大括号集,编译器就可以自由地将内存重新用于函数中的其他变量,我有意这样做有两个原因:

  • 变量很大,但只需要很短的时间,所以为什么要使堆栈大于需要?
  • 如果一个变量只在有限的时间内有一个正常的值,并且在这个范围之外使用会有危险或错误,那么就添加额外的花括号,这样不正确的使用就会产生编译器错误。

示例:

your_function(int a)
{
   int stack_1;
  { 
     int limited_scope_1[10000];
     do_something(a,limited_scope_1);
  }
  { 
     int limited_scope_2[10000];
     do_something_else(a,limited_scope_2);
  }       
}

相关问题