C语言中的For循环局部变量

18
为什么以下代码每次输出的都是同一个内存地址?
int x;
for (x = 0; x < 10; x++) {
    int y = 10;
    printf("%p\n", &y);
}

我原本认为每次运行for循环时,内存位置都应该会改变,因为变量是新的。

4个回答

20

没错,你说的没错,内存位置可能会改变。但是这并非必然情况:)在每次迭代中,旧变量将被“销毁”,在同一位置创建一个新变量。尽管任何好的编译器都会优化掉不必要的“操作”。


1
好的,谢谢。我把这个问题过于简化了,实际上我正在尝试创建一个链表,在for循环中创建一个新节点,但我不希望下一个节点覆盖上一次迭代的节点,但它确实是这样做的。一旦我能够生成一个可以轻松分析的代码片段,我会发布一个新问题。 - Amandeep Grewal
4
如果您希望使用持久的数据结构,它们必须在“堆”而不是“栈”上创建。为此,请使用“malloc”等函数。 - Alnitak
1
@amandeepGrewal:为了实现所需的行为,您应该在堆上创建变量(使用malloc)。 - Armen Tsirunyan

6

是的,每次循环变量都是新的,但在块结束时,堆栈上的任何新变量都会被释放。

因此下一次堆栈指针回到了原来的位置。注意:这种行为很常见,但并不被标准保证。


5

这是一种编译器优化。因为局部变量即将超出作用域,而一个完全相同类型的变量即将被创建,所以它会重用内存地址。需要注意的是,就你的程序而言,这仍然是一个“新”的变量。

比较以下代码片段和输出:

for (i = 0; i < 3; i++) {
    int n = 0;
    printf("%p %d\n", (void *)&n, n++);
}
0x7fff56108568 0
0x7fff56108568 0
0x7fff56108568 0
三行数字表示内存地址和其中存储的值,属于计算机科学中的概念。
for (i = 0; i < 3; i++) {
    static int n = 0;
    printf("%p %d\n", (void *)&n, n++);
}
0x6008f8 0
0x6008f8 1
0x6008f8 2

0

变量的作用域规则仅描述您有权访问局部变量的范围:从定义到其块的结尾。

这个规则并没有说明为它保留空间的时刻。一个常见的策略是在函数开始时一次性为所有需要的变量保留空间。

因此,当执行穿过变量的定义时,通常不需要做任何特别的事情,也不需要单独的指令。另一方面,这将变量的值留给了之前找到的任何内容。因此,在已知状态下初始化的重要性就像您在示例中使用的= 10一样。


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