【问题标题】:How are allocated arrays declared in a loop?如何在循环中声明分配的数组?
【发布时间】:2020-03-27 13:46:51
【问题描述】:

我对这个功能感到困惑。

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

return 0;

空间如何在有界(由 ESP)堆栈内存中增长? 有没有一种编译技巧?

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

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

在第一个循环之后

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

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

【问题讨论】:

  • 什么是“ESP”?您是在谈论特定架构吗?有些架构没有“堆栈指针”。并且堆栈可以在不同的架构上向上或向下(或者,在任何地方)增长。 编译器实现它的方式取决于它。
  • 栈指针,栈底地址。特定于具有堆栈指针的架构级别

标签: c arrays stack static-allocation


【解决方案1】:

空间如何在有限大小的堆栈内存中增长?

您指的是char arr 的空间-它的空间不会增长。它是for 循环范围内的局部变量。所以每次循环有一个新的i,它就是一个全新的char arr

【讨论】:

    【解决方案2】:

    有什么编译技巧吗?

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

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

    https://godbolt.org/z/_uR9Ac

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

    【讨论】:

      【解决方案3】:

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

      有点不同的例子

      #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 行分配空间 然后第 28 行为数组释放空间

      https://godbolt.org/z/msgrc2

      【讨论】:

      • 这里memset有什么用?
      • 防止优化
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 2015-04-23
      • 2012-04-29
      相关资源
      最近更新 更多