可变长度数组(VLA)在 C99 标准中引入,在此之前,所有数组的大小必须在编译时已知。它们允许声明在运行时仅通过变量确定大小的数组。
不正确使用 VLA 会导致未处理的内存分配错误(例如,过大的数组会导致堆栈溢出),无法在不同编译器之间传递 VLA(并非所有编译器都支持它们),以及与更旧的 C 和 C++ 标准的兼容性有限。此外,调试复杂,因为内存是在栈上分配的,而不是在堆上,这并不总是可以预期的。
使用 VLA 时,必须记住它们在栈上,并且不能是全局或静态的。如果需要灵活性并保证与 C++ 的兼容性,最好使用通过 malloc 分配的动态数组。为了兼容性,如果不保证支持 VLA,最好仅使用静态数组或 C90 标准。
代码示例:
#include <stdio.h> void process(size_t n) { int arr[n]; // VLA for(size_t i = 0; i < n; i++) arr[i] = i; for(size_t i = 0; i < n; i++) printf("%d ", arr[i]); } int main() { process(5); return 0; }
关键特性:
可以在函数内部声明可变长度的静态数组,像这样 static int arr[n]; 吗?
不可以,静态变量在编译时必须具有确定的大小。因此,static int arr[n];会导致编译错误。
VLA 在退出函数时会自动释放吗?
是的,VLA 分配在栈上,它们的内存在退出块/函数时自动释放,就像普通的局部变量一样。
分配非常大的 VLA 是否安全?
不安全,栈的大小是有限的(例如,1 MB 或 8 MB)。尝试分配大的 VLA 会导致运行时错误(栈溢出)。
编写了使用 VLA 的跨平台代码,代码在旧的或高度配置的编译器上无法编译。
优点:
缺点:
仅在保证小尺寸的局部任务中使用 VLA,对于大型数组 — 使用 malloc/free。
优点:
缺点: