可变长数组
可变长数组是指在计算机程序设计中,数组对象的长度在运行时(而不是编译时)确定。[1]
支持可变长数组的程序设计语言有:Ada, ALGOL 68 (for non-flexible rows), APL, C99 (以及C11[2][3][4] ) ,C# [5], COBOL, Fortran 90, J。
C/C++的灵活数组类型(又称柔性数组成员)是另外一个语言特性。
可增长数组(也叫做动态数组)是不同的概念,很多编程语言比如JavaScript、Java、Python和R等只支持可增长数组。
语言细节
C99
下述C99函数内部创建了一个可变长数组的局部变量。因为该数组被声明为一个局部变量,所以它会在read_and_process
函数返回时自动销毁。
float read_and_process(int n)
{
float vals[n];
for (int i = 0; i < n; i++)
vals[i] = read_val();
return process(vals, n);
}
在C99中,进行函数调用时,变长数组的长度必须在变长数组本身之前进行传入。在C11中,如果编译器不支持VLA(变长数组)的话,编译器本身会定义一个叫做__STDC_NO_VLA__
的宏。在C99之前,GCC就已经把VLA作为一个有用的扩展了。
但是Linus Torvalds表达了对可以预见长度的小数组仍然使用VLA(变长数组)的情况不太满意,并(在一段加密程序代码中)写下如下注释:“USING VLA'S IS ACTIVELY STUPID! It generates much more code, and much slower code (and more fragile code), than just using a fixed key size would have done.”(相比单纯使用一个固定的密钥长度,使用变长数组太蠢了,因为它生成的机器码多得多,运行起来慢得多(维护起来还更容易出问题))。有鉴于此,Linux kernel项目从头到尾都没有使用过一处变长数组。
C++
C++0x标准不支持变长数组[6]。
但是作为一个有用的扩展,g++和clang++对VLA做了一些支持(但请注意,它并不是标准化的一部分)。
作为替代,建议使用C++标准下的STL容器std::vector,或者使用new和delete[]来动态地为数组分配内存。
其他
同样的功能用Ada表示:
type Vals_Type is array (Positive range <>) of Float;
function Read_And_Process (N : Integer) return Float is
Vals : Vals_Type (1 .. N);
begin
for I in 1 .. N loop
Vals (I) := Read_Val;
end loop;
return Process (Vals);
end Read_And_Process;
等价的Fortran 90函数:
function read_and_process(n) result(o)
integer,intent(in)::n
real::o
real,dimension(n)::vals
real::read_val, process
integer::i
do i = 1,n
vals(i) = read_val()
end do
o = process(vals, n)
end function read_and_process
COBOL代码片段:
DATA DIVISION.
WORKING-STORAGE SECTION.
01 DEPT-PEOPLE.
05 PEOPLE-CNT PIC S9(4) BINARY.
05 DEPT-PERSON OCCURS 0 TO 20 TIMES DEPENDING ON PEOPLE-CNT.
10 PERSON-NAME PIC X(20).
10 PERSON-WAGE PIC S9(7)V99 PACKED-DECIMAL.
C#函数:
unsafe void declareStackBasedArray(int size)
{
int *pArray = stackalloc int[size];
pArray[0] = 123;
}
参考文献
- ^ 存档副本. [2014-12-19]. (原始内容存档于2018-04-03).
- ^ http://pic.dhe.ibm.com/infocenter/ratdevz/v8r0/topic/com.ibm.xlcpp111.aix.doc/language_ref/variable_length_arrays.html
- ^ 存档副本. [2014-12-19]. (原始内容存档于2020-12-05).
- ^ ISO 9899:2011 Programming Languages - C 6.7.6.2 4
- ^ 作为unsafe-mode stack-allocated arrays
- ^ https://stackoverflow.com/questions/1887097