如何在循环中声明分配的数组?

How are allocated arrays declared in a loop?

我对这个功能感到困惑。

int i;
for(i = 1; i<10; i++){
        int arr[i];
        printf("%d\n",sizeof(arr));
    }

return 0;

space 如何在有界(通过 ESP)堆栈内存中增长? 有什么编译技巧吗?

编辑解释: 堆栈不应该是这样的吗?

0  ---> val of i uninitialized
-4 ---> arr[0] uninitialized

在第一个循环之后

0  ---> val of i uninitialized
-4 ---> arr[1] uninitialized
-8 ---> arr[0] uninitialized

我很想说:ESP 是否在循环的每次迭代下方移动?

How can the space grow in a bounded size stack memory?

您指的是 char arr 的 space - 它的 space 没有增长。它是 for 循环范围内的局部变量。所以每次循环都有一个新的 i 它是一个全新的 char arr.

Is there a sort of compilation trick?

是的,有点。它使用 VLA (https://en.wikipedia.org/wiki/Variable-length_array)

Godbolt 对于检查这样的事情非常有用:

https://godbolt.org/z/_uR9Ac

如您所见,确实针对相关行触发了 -Wvla 警告。

在每个循环中,都会为数组分配堆栈,然后释放。

有点不同的例子

#include "stdio.h"
#include "string.h"

int h(int x) 
{
    for(int i = 1; i<x; i++){
            char arr[i];
            memset(arr, i, sizeof(arr));
            printf("%d\n",sizeof(arr));
        }
    return 0;
}

int main()
{
   h(50);
}

编译后的代码


.LC0:
        .string "%d\n"
h:
        push    rbp
        mov     rbp, rsp
        push    r13
        push    r12
        mov     r12d, edi
        push    rbx
        mov     ebx, 1
        push    rax
.L2:
        cmp     r12d, ebx
        jle     .L6
        lea     rax, [rbx+15]
        mov     r13, rsp
        mov     ecx, ebx
        mov     rsi, rbx
        and     rax, -16
        sub     rsp, rax
        mov     eax, ebx
        inc     rbx
        mov     rdi, rsp
        rep stosb
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        mov     rsp, r13
        jmp     .L2
.L6:
        lea     rsp, [rbp-24]
        xor     eax, eax
        pop     rbx
        pop     r12
        pop     r13
        pop     rbp
        ret
main:
        push    rax
        mov     edi, 50
        call    h
        xor     eax, eax
        pop     rdx
        ret

第 15、19 和 20 行分配 space 第 28 行为数组

解除分配 space

https://godbolt.org/z/msgrc2