您的位置:首页 > 其它

关于VLA(变长数组)

2020-08-29 12:03 85 查看

1. 数组长度不能用变量定义

我学数组的第一天起,我的老师告诉我不能用变量来声明一个数组的长度。比如这样的方式是不对的:

#include <stdio.h>
int main() {
int n;
scanf("%d", &n)
int a[n];

}

这样也是不对的:

#include <stdio.h>
int main() {
int n = 5;
int a[n];
}

原因是:编译的时候需要给数组分配空间,而

n
是在运行时才被确定的。

所以对于只有在运行时才能确定数组长度的情况,基本有两种解决方式:

  1. 把数组的长度开的尽可能大,大到一定可以存放下你所有的元素即可。
  2. 自己动态分配内存,使用
    malloc(number * sizeof(type))
    ,使用完了再
    free
    掉这块手动申请的内存。

2. 但其实也并不是这样

当时我使用的编译器是msvc,后来的某天我换成了clang。神奇的事情发生了,上面那段代码完全没有任何问题。

查了很多资料,发现了VLA(变长数组)这样一种概念。我又有了如下的疑惑:

  • 数组需要在编译的时候分配空间,那么变长数组又是怎么实现的呢?
  • 既然可以实现变长数组,为什么它不在c99标准中而且很少有人去使用它呢?

3. 数组的内存

在讨论上面两个问题之前,讨论一下数组的内存是十分必要的。

首先,对于

int a[10]
这类的数组声明,数组的所有内存都分配在栈里。

然而对于

type *a = malloc(number * sizeof(type))
这类的数组,分配的是堆空间中的内存,栈中储存
*a
这一指针,用于引用堆中的内存。所以在结束使用的时候需要手动释放掉这部分内存,否则就会造成memory leaking(内存泄漏)。

4. 问题的解答

(1)变长数组的实现

变长数组是通过动态分配栈顶来实现的。【这个以后我搞明白了再细讲】

(2)为什么不推荐使用变长数组

由于变长数组是分配在栈里的,栈空间可以使用的内存要远远少于堆空间中可使用的内存。并且一个程序的运行是离不开栈来记录程序的运行状态的。

数组作为一个“存放各种元素的集合”,很有可能占用很大一部分内存空间。一旦所有的栈空间都被数组占满了,程序也无法运行了。因此,把数组,尤其是大数组分配在堆里,栈里只存放一个引用是更合理的方式。

5. Java中的数组

Java认为:“一切都是对象”,Java中的对象也存放在堆中。因此,Java中的数组内存分配方式类似于

malloc
,即所有的元素实际存放在堆中,栈中只留下一个引用。只不过JVM的垃圾回收机制使得你不用再手动释放内存了而已。

因此,在Java中使用变量作为数组长度,或者根据运行时的输入确定数组长度是完全没有问题的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: