【问题标题】:What happens to variable x in this for loop in C?C 中的这个 for 循环中的变量 x 会发生什么?
【发布时间】:2017-04-01 18:10:48
【问题描述】:

在下面这段代码中

int main(){
int i;
for(i = 0;i<4;i++){
int x = 1;
x++;
} // for close
}// main close

这里的变量x是`auto storage class,对吧?

那么,变量x会被创建吗,我的意思是内存分配发生在遇到语句并在到达循环结束并被创建时被销毁/再次为x分配内存?

我试图在循环中打印x 的地址,它每次都为x 打印相同的地址。所以,这是否意味着每次创建和销毁x 并且它使用相同的房间/内存阻止它?

如果它像这样创建和销毁,它不会影响 CPU 使用率吗? 如果是这样,有什么方法可以预防并保持良好的记忆健康?

【问题讨论】:

    标签: c memory-management dynamic-memory-allocation static-memory-allocation


    【解决方案1】:

    简短的回答是“什么都没有”。任何优化编译器都会优化这个变量,因为它永远不会被读取。

    即使关闭优化器,变量也会在进入函数时分配一次,然后在每次迭代中设置为 1,然后递增。

    分配非常便宜,因为它在自动存储中。空间是在编译时决定的,所以在运行时它不会花费你任何东西。所有迭代都重用相同的位置,因此不会因迭代而产生额外成本。

    【讨论】:

    • 优化器的意思是...你的意思是 volatile 关键字吗?你说它从未读过是什么意思!!!!?!?!提前致谢
    • @Curiousboy 优化器是编译器的最后阶段,当它确定指令是否可以重新排序或删除以使代码运行得更快时。 “从不阅读”是指没有使用 x 值的打印或其他表达式。
    【解决方案2】:

    它取决于实现。您会看到相同的内存地址,因为编译器决定这样做。在每次迭代之前,内存不会神奇地分配到新地址。 x86 架构中的自动存储是使用堆栈实现的,分配只需减去指向堆栈顶部的ESP/RSP (x86/x64) 寄存器即可。您可以在互联网上阅读有关它的文章。

    编译器只是在每次迭代时重新分配内存(不分配/解除分配)

    这是您的代码(GCC 6.3,x86)的汇编列表。汇编语言中的注释以; 开头。我添加了类似c的伪代码来解释指令的含义

    main:
            push    ebp
            mov     ebp, esp ; Create new stack frame
            sub     esp, 16 ; Allocate memory for local variables
            mov     DWORD PTR [ebp-4], 0 ; i = 0;
    .L3:
            cmp     DWORD PTR [ebp-4], 3  ; if(i > 3)
                                          ; {
            jg      .L2                   ;    break;
                                          ; }
            mov     DWORD PTR [ebp-8], 1 ; x = 1;
            add     DWORD PTR [ebp-8], 1 ; x += 1;
            add     DWORD PTR [ebp-4], 1 ; i += 1;
            jmp     .L3 ; Go to location .L3
    .L2:
            mov     eax, 0 ; Set return value to 0
            leave ; Restore the stack pointer
            ret ; Return to the caller
    

    所以ebp - 8(或int x)的地址每次都相同。

    这是优化的代码汇编列表(GCC 6.3、֊O3、x86)。

    main:
            xor     eax, eax ; Set return value to 0
            ret ; Return to the caller
    

    【讨论】:

      【解决方案3】:

      是的,循环中的每一轮都会构造和销毁变量。

      但是,正如您所注意到的,编译器足够聪明,每次都可以为变量重用相同的存储空间。可能在堆栈上,当进入函数时,空间可能已经被分配。所以不用担心“内存管理”。

      如果你开启一些优化,编译器也可能会注意到没有一个变量真正用于任何事情,并删除所有代码。

      【讨论】:

        【解决方案4】:

        在 for 循环的每次迭代中,您都在创建变量“x”,将其设置为 1,然后将其递增为 2。“x”正在被销毁,因为它只存在于 for 循环中。如果您不希望每次迭代都创建和销毁它,您可以简单地在 for 循环上方声明它。

        但是,您究竟想用这段代码完成什么?它似乎没有多大作用。此外,由于您担心内存分配,因此可以在 for 循环中声明变量“i”,这样您就不会在完成 for 循环后让它徘徊。

        【讨论】:

        • 嗨@Silamoth,在某种意义上被破坏了......在退出循环或每次迭代之后?
        • 每次迭代后,它都会被销毁。换句话说,它将被创建和销毁 4 次。然而,正如其他人所说,一个智能的现代编译器最终将重用变量及其位置,因为它每次迭代都会重新创建。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多