Variabel længde - Variable-length array
I computerprogrammering er en array med variabel længde ( VLA ), også kaldet variabel størrelse eller runtime-størrelse , en array datastruktur, hvis længde bestemmes ved løbetid (i stedet for på kompileringstidspunktet). I C siges VLA at have en variabelt modificeret type, der afhænger af en værdi (se afhængig type ).
Hovedformålet med VLA'er er at forenkle programmering af numeriske algoritmer.
Programmeringssprog, der understøtter VLA'er, inkluderer Ada , Algol 68 (for ikke-fleksible rækker), APL , C99 (selvom de senere blev henvist i C11 til en betinget funktion, som implementeringer ikke er nødvendige for at understøtte; på nogle platforme, kunne implementeres tidligere med alloca()eller lignende funktioner) og C# (som stackable-allokerede arrays i usikker tilstand), COBOL , Fortran 90 , J og Object Pascal (sproget, der bruges i Borland Delphi og Lazarus , der bruger FPC).
Hukommelse
Tildeling
- The GNU C Compiler Allokerer hukommelse til VLAS med automatisk varighed opbevaring på stakken . Dette er den hurtigere og mere ligetil løsning sammenlignet med bunktildeling, og bruges af de fleste kompilatorer.
- VLA'er kan også tildeles på bunken og få adgang internt ved hjælp af en markør til denne blok.
Implementering
C99
Den følgende C99- funktion tildeler en array med variabel længde af en bestemt størrelse, fylder den med floating-point-værdier og sender den derefter til en anden funktion til behandling. Fordi matrixen er erklæret som en automatisk variabel, slutter dens levetid, når den read_and_process()vender tilbage.
float read_and_process(int n)
{
float vals[n];
for (int i = 0; i < n; ++i)
vals[i] = read_val();
return process(n, vals);
}
I C99 skal længdeparameteren komme før parameteren med variabel længde i funktionsopkald. I C11 __STDC_NO_VLA__defineres en makro, hvis VLA ikke understøttes. GCC havde VLA som en udvidelse før C99, en der også strækker sig ind i dens C ++ dialekt.
Linus Torvalds har tidligere udtrykt sin utilfredshed med VLA -brug for arrays med forudbestemte små størrelser, fordi den genererer en lavere kvalitetskode. Med Linux 4.20-kernen er Linux-kernen effektivt VLA-fri.
Selvom C11 ikke eksplicit navngiver en størrelsesbegrænsning for VLA'er, mener nogle aflæsninger, at den skal have den samme maksimale størrelse som alle andre objekter, dvs. SIZE_MAX bytes. Denne læsning bør imidlertid forstås i den bredere kontekst af miljø- og platformgrænser, f.eks. Den typiske stack-guard-sidestørrelse på 4 KiB, som er mange størrelsesordener mindre end SIZE_MAX.
Det er muligt at have VLA'er med dynamisk lagring ved hjælp af en markør til et array.
float read_and_process(int n)
{
float (*vals)[n] = malloc(sizeof(int[n]));
for (int i = 0; i < n; ++i)
(*vals)[i] = read_val();
float ret = process(n, *vals);
free(vals);
return ret;
}
Ada
Følgende er det samme eksempel i Ada . Ada -arrays har deres grænser med sig, så det er ikke nødvendigt at videregive længden til procesfunktionen.
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
Den tilsvarende Fortran 90 -funktion er
function read_and_process(n) result(o)
integer,intent(in)::n
real::o
real,dimension(n)::vals
integer::i
do i = 1,n
vals(i) = read_val()
end do
o = process(vals)
end function read_and_process
ved anvendelse af Fortran 90 -funktionen til kontrol af proceduregrænseflader på kompileringstidspunktet; på den anden side, hvis funktionerne bruger pre-Fortran 90-opkaldsgrænseflade, skal de (eksterne) funktioner først deklareres, og arraylængden skal eksplicit sendes som et argument (som i C):
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
Følgende COBOL- fragment erklærer en række poster DEPT-PERSONmed variabel længde med en længde (antal medlemmer) angivet med værdien af PEOPLE-CNT:
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.
Den COBOL VLA, til forskel fra andre sprog nævnes her, er sikkert fordi COBOL kræver en til at angive den maksimale array-størrelse - i dette eksempel, DEPT-PERSONkan ikke have mere end 20 varer, uanset værdien af PEOPLE-CNT.
C#
Det følgende C# -fragment erklærer en række af hele tal med variabel længde. Før C# version 7.2 kræves en markør til arrayet, der kræver en "usikker" kontekst. Søgeordet "usikkert" kræver, at en samling, der indeholder denne kode, markeres som usikker.
unsafe void DeclareStackBasedArrayUnsafe(int size)
{
int *pArray = stackalloc int[size];
pArray[0] = 123;
}
C# version 7.2 og nyere tillader, at arrayet tildeles uden det "usikre" søgeord ved hjælp af Span -funktionen.
void DeclareStackBasedArraySafe(int size)
{
Span<int> stackArray = stackalloc int[size];
stackArray[0] = 123;
}
Objekt Pascal
På dette sprog kaldes det et dynamisk array. Deklarationen af en sådan variabel svarer til erklæringen om et statisk array, men uden at specificere dens størrelse. Størrelsen af arrayet er angivet på tidspunktet for dets anvendelse.
program CreateDynamicArrayOfNumbers(Size: Integer);
var
NumberArray: array of LongWord;
begin
SetLength(NumberArray, Size);
NumberArray[0] := 2020;
end.
Fjernelse af indholdet i et dynamisk array foretages ved at tildele det en størrelse på nul.
...
SetLength(NumberArray, 0);
...