【问题标题】:Creating Dynamic Array without malloc [duplicate]创建没有malloc的动态数组[重复]
【发布时间】:2016-01-24 11:44:50
【问题描述】:

我很惊讶地看到这段代码可以正常工作。我不知道为什么

#include<stdio.h>
int main(){
  int row,col,i,j;
  scanf("%d %d",&row,&col);
  int a[row][col];
  for(i=0;i<row;i++)
      for(j=0;j<col;j++)
           scanf("%d",&a[i][j]);
   for(i=0;i<row;i++){
      for(j=0;j<col;j++)
           printf("%d ",a[i][j]);
       printf("\n");
   }
}

既然 C 是一种编译语言,那么它是如何为数组 a[row][col] 分配内存的?既然在编译的时候不知道行列的值,那它是如何制作机器码和给程序设置地址空间的呢?为什么这是作为解释器语言工作的原因,如果这是一种创建动态数组的方法,那么为什么要教我们使用 ma​​lloc 在 C 中创建动态数组。

【问题讨论】:

  • 其实不是动态数组而是半动态的

标签: c c99


【解决方案1】:

自 C99 以来,可变长度数组一直是 C 的标准特性。

它是如何为数组a[row][col]分配内存的

一旦知道rowcol的值,编译后的代码在自动存储区(通常称为“栈”)中进行分配是没有问题的。

它是如何生成机器码并为程序设置地址空间的?

编译器将rowcol 的值隐藏起来,供其生成的机器代码在内部使用。引用 a[i][j] 的指令会查找大小、进行数学运算、添加偏移量并获取地址,就好像 rowcol 在编译时已知一样。

该功能确实改变了其他一些事情 - 例如,sizeof 不再是纯粹的编译时操作,因为需要在运行时计算 VLA 的大小。

为什么教我们使用 malloc 在 C 中创建动态数组。

malloc 为您提供比 VLA 更大的灵活性。例如,您可以从您的函数返回一个 malloc-created 数组,而 VLA 会在函数完成后自动释放。此外,malloc 不太可能在内存不足的情况下运行您的程序,因为动态存储区域比自动存储区域更大。

例如,如果您尝试为您的程序输入20002000,它很可能会崩溃。然而,使用malloc 分配相同数量的内存没有问题:

int (*a)[col] = malloc(row*col*sizeof(int));

【讨论】:

    【解决方案2】:

    That's feature of C99。无论如何使用malloc 的原因是它分配的空间不是在堆栈上,而是在堆上——而堆是应该存储“重”数据的地方,因为堆栈空间受到严重限制。比那更多的;未能进行堆栈分配通常会使程序崩溃 - 当使用 malloc 进行分配时返回一个 NULL 指针,这使您可以以优雅的方式继续。

    【讨论】:

    • 没有此功能也适用于早期版本的 C。
    • C 标准中没有提到堆或堆栈(至少,没有在作为不同内存区域的上下文中),更不用说在堆栈中分配任何 VLA 要求
    • @ASEN - 第一个支持 VLA 的 C 标准是 1999 年的 C 标准。在此之前,一些实现支持诸如扩展之类的东西。
    • 谢谢彼得,我不知道我使用的是 C89,它可以工作,所以我说
    猜你喜欢
    • 2021-03-29
    • 2011-10-03
    • 2017-03-29
    • 2017-03-08
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    相关资源
    最近更新 更多