当我只能定义一个可变长度数组时,为什么要使用malloc()?

时间:2018-07-20 18:15:21

标签: c arrays

我正在阅读有关在C中动态创建数组的知识。因此,这里描述的正确方法是:

int n;
scanf("%d", &n);
int *arr = (int*)malloc(n*sizeof(int));

但是后来我想我是否可以做这样的事情-

int n, i, sum=0;
scanf("%d", &n);
int arr[n];

我编译并运行了它,没有任何错误。因此,我的问题是为什么我应该使用malloc()?这与新旧C版本有关吗?

2 个答案:

答案 0 :(得分:8)

在可变长度数组上使用malloc至少有五个好处。

  1. 最值得注意的是,用malloc创建的对象在当前块的执行结束后仍然存在。这意味着可以将这些对象(通过指针)返回给函数的调用者。在实际应用中,这种用法很常见。创建为可变长度数组的数组在其块执行结束时不复存在。

  2. malloc创建的数组可以用realloc调整大小。可变长度数组无法调整大小。

  3. 从2011 C标准开始,可变长度数组对于C实现是可选的。任何质量的通用C实现都将支持它们,但事实是它们是可选的,意味着要移植的代码必须不使用可变长度数组,或者必须通过测试预处理器宏{{ 1}},并提供备用代码。

  4. 常见的可变长度数组的大小比__STDC_NO_VLA__分配的数组要受限制。可变长度数组通常使用堆栈空间来实现,并且堆栈通常限于不大一些的兆字节(尽管在构建可执行文件时通常可以增加字节数)。对于使用malloc创建的对象,在现代系统中可能有千兆字节的内存。

  5. 如果创建数组确实失败malloc,则将返回malloc,程序员可以轻松编写代码以检测并对其进行处理。如果创建可变长度数组失败,则常见的行为是操作系统因内存错误而终止程序。 (各种C实现可能提供了拦截此错误的方法,但比测试NULL的{​​{1}}返回值要麻烦得多,并且它不是可移植的。)

答案 1 :(得分:2)

  

我编译并运行它没有任何错误。所以,我的问题是为什么我真的应该使用malloc()?这与新旧C版本有关吗?

堆栈分配的数组不等同于免费存储中的缓冲区(堆,malloccalloc使用的内存区域)。

  1. 假定数组存在于堆栈中(隐含为自动变量),则您的数组不能超过平台的最大堆栈大小。在具有pthreads的Linux上,默认值为2 MB。该限制在Windows上相似。

  2. 由于作用域和对象生存期的原因:指向堆栈中存在的数组元素的指针的生存期不能长于它们指向的数组的生存期,这意味着您不能在指向它们的作用域之后返回指向这些数组和元素的指针重新声明过期。

  3. VLA阵列在C11中是可选的。在C ++中,它们根本不属于规范的一部分(即它们是供应商扩展),因此您的代码将不可移植。