Register__ 2022-03-16 23:47 采纳率: 89.5%
浏览 28
已结题

C语言数组申请的问题

问题:C99 中 数组的长度可以动态申请,底层是如何实现的?(我不确定是不是C99)
学过一点函数堆栈图,函数开栈的时候要知道自己要开多大的空间,这就要知道这个函数体中的所有变量要用多大的空间(不是new 、malloc 出来的变量在函数开的栈中),之前做题的时候看到有题解没有malloc 也没有new 直接int a[n],这种是不是编译器主动把它开到堆中了,如果不开在堆中,说不过道理啊?

  • 写回答

3条回答 默认 最新

  • _GX_ 2022-03-17 04:21
    关注

    变长数组是C99的新特性,它是在栈上分配的,下面是一个简单例子,用clang编译器在x64架构上生成的代码进行解析。

    void f(int n)
    {
        int a[n];
        a[0] = 1;
        a[1] = 2;
    }
    
    
    f:                                      # @f
            push    rbp                             ; 保存帧指针
            mov     rbp, rsp                        ; 当前帧指针
            sub     rsp, 32                         ; 在栈上分配32个字节内存空间
            mov     dword ptr [rbp - 4], edi        ; edi是函数传入的第一个参数,将其赋值给实参/局部变量n,*(rbp-4) = n
            mov     eax, dword ptr [rbp - 4]        ; eax = n
            mov     ecx, eax                        ; ecx = n
            mov     rax, rsp                        ; rax = rsp
            mov     qword ptr [rbp - 16], rax       ; 保存栈指针rsp到rbp-16,*(rbp-16) = rsp
            lea     rdx, [4*rcx + 15]               ; 接下来两个指令是计算在栈上分配VLA数组的内存大小,rdx=(sizeof(int)*n+15)/16*16,按16字节对齐
            and     rdx, -16                        ; 
            mov     rax, rsp                        ; 计算rsp = rax = rsp - rdx,即在栈上分配内存,rax是VLA数组首地址
            sub     rax, rdx                        ;
            mov     rsp, rax                        ;
            mov     qword ptr [rbp - 24], rcx       ; 保存数组长度n
            mov     dword ptr [rax], 1              ; a[0] = 1
            mov     dword ptr [rax + 4], 2          ; a[1] = 2
            mov     rax, qword ptr [rbp - 16]       ; rax = 原栈指针 
            mov     rsp, rax                        ; 恢复栈指针,释放VLA数组内存
            mov     rsp, rbp                        ; 释放局部变量内存
            pop     rbp                             ; 恢复帧指针
            ret                                     ; 函数返回
    
                      .
                      .
                      .
    
           4  +------------------+
              | 调用函数帧指针rbp |
           0  +------------------+ <---- 当前函数帧指针rbp
              |     实参n        |
          -4  +------------------+
              |                  |
          -8  +------------------+
              |     保存的        |
         -12  +    栈指针rsp      +
              |    占8个字节      |
         -16  +------------------+
              |    VLA数组        |
         -20  +   元素数目n       +
              |   占8个字节       |
         -24  +------------------+
              |                  |
              +------------------+
              |                  |  a[n-1]
              +------------------+
                      .
                      .
                      .
              +------------------+
              |       2          |  a[1]
              +------------------+
              |       1          |  a[0]
              +------------------+        <---- rsp, rax变长数组(VLA)首地址
                      .
                      .
                      .
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 3月25日
  • 已采纳回答 3月17日
  • 创建了问题 3月16日

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)