关于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是在运行时才被确定的。
所以对于只有在运行时才能确定数组长度的情况,基本有两种解决方式:
- 把数组的长度开的尽可能大,大到一定可以存放下你所有的元素即可。
- 自己动态分配内存,使用
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中使用变量作为数组长度,或者根据运行时的输入确定数组长度是完全没有问题的。
相关文章推荐
- 关于高维数组计算的一些优化
- 关于继承多态和数组那错综复杂的关系
- ## 关于数组的概念及基本操作思想
- 关于数组的一些简单操作
- 关于数组的认识01 - 零基础入门学习Delphi15
- 关于C#的垃圾回收以及List动态数组的用法。
- java关于数组去重
- 关于java数组的学习心得
- 在C/C++中关于局部数组问题(子函数等)
- 关于数组做函数形参和指针做函数形参的问题
- 关于数组的求和、对角线求和、矩阵转置、杨辉三角
- 关于函数指针数组与返回数组指针的函数
- 关于JAVA 数组的使用介绍
- 关于函数指针数组与返回数组指针的函数
- 关于数组添加值和访问值的一些小问题
- 个人练习数据结构之--------------关于线性数据的有序数组以及之上的二分法查找、不同排序方法的学习
- 关于多态和数组的比较
- 关于sizeof在调用函数中获取被调函数数组长度的思考
- 关于逆序对的一种运用(树状数组)
- 发现关于数组求其长度 strlen 和 sizeof的问题