变长数组(VLA)和调用malloc()在功能上有些重合。例如,两者都可用于创建在运行时确定大小的数组:
int vlamal()
{
int n;
int * pi;
scanf("%d", &n);
pi = (int *) malloc (n * sizeof(int));
int ar[n]; // vla
pi[2] = ar[2] = -5;
...
}
不同的是,变长数组是自动存储类型。因此,程序在离开变长数组定义所在的块时(该例中,即vlamal()函数结束时),变长数组占用的内存空间会被自动释放,不必使用free()。另一方面,用malloc()创建的数组不必局限在一个函数内访问。例如,可以这样做:被调函数创建一个数组并返回指针,供主调函数访问,然后主调函数在末尾调用free()释放之前被调函数分配的内存。另外,free()所用的指针变量可以与malloc()的指针变量不同,但是两个指针必须存储相同的地址。但是,不能释放同一块内存两次。
对多维数组而言,使用变长数组更方便。当然,也可以用malloc()创建二维数组,但是语法比较繁琐。如果编译器不支持变长数组特性,就只能固定二维数组的维度,如下所示:
int n = 5;
int m = 6;
int ar2[n][m]; // n x m VLA
int (* p2)[6]; // works pre-C99
int (* p3)[m]; // requires VLA support
p2 = (int (*)[6]) malloc(n * 6 * sizeof(int)); // n * 6 array
p3 = (int (*)[m]) malloc(n * m * sizeof(int)); // n * m array
// above expression also requires VLA support
ar2[1][2] = p2[1][2] = 12;
先复习一下指针声明。由于malloc()函数返回一个指针,所以p2必须是一个指向合适类型的指针。第1个指针声明:
int (* p2)[6]; // works pre-C99
表明p2指向一个内含6个int类型值的数组。因此,p2[i]代表一个由6个整数构成的元素,p2[i][j]代表一个整数。
第2个指针声明用一个变量指定p3所指向数组的大小。因此,p3代表一个指向变长数组的指针,这行代码不能在C90标准中运行。