Pole s proměnnou délkou

V programování je pole proměnné délky ( VLA, pole proměnné velikosti, pole velikosti runtime ) pole , jehož délka je určena v době běhu (a ne v době kompilace) [1] . V C má pole s proměnnou délkou typ spravovaný proměnnou ( angl. variabilně modifikovaný typ ), který závisí na nějaké hodnotě (viz Závislý typ ).   

Hlavním účelem polí proměnné délky je zjednodušit programování numerických algoritmů.

Programovací jazyky, které podporují pole s proměnnou délkou: Ada , Algol 68 (bez možnosti měnit délku řetězců ve dvourozměrných polích atd.), APL , C99 (ačkoli později se pole s proměnnou délkou stalo volitelnou funkcí v C11 , jehož podpora není vyžadována [2] [3] ; na některých platformách to mohlo být již dříve implementováno pomocí funkce alloca()nebo podobně) a C# (pole alokovaná na zásobníku – tato funkce je dostupná pouze v nebezpečném režimu), COBOL , Fortran 90 , J a Object Pascal (jazyk používaný v prostředí LazarusaBorland Delphi , zkompilovaný pomocí kompilátoru Free Pascal).

Paměť

Alokace paměti

Implementace

C99

Následující funkce C99 alokuje pole s proměnnou délkou dané velikosti, naplní je hodnotami s plovoucí desetinnou čárkou a poté je předá jiné funkci ke zpracování. Protože je pole deklarováno jako automatická proměnná, jeho životnost končí, když read_and_process().

float read_and_process ( int n ) { plovákové valy [ n ]; for ( int i = 0 ; i < n ; ++ i ) val [ i ] = read_val (); návratový proces ( n , val ); }

V C99 musí parametr length předcházet parametru pole proměnné délky ve volání funkcí [1] . C11 definuje makro __STDC_NO_VLA__, pokud pole s proměnnou délkou nejsou podporována [5] . GCC měl pole s proměnnou délkou jako rozšíření před C99, které také zasahuje do jeho dialektu C++.

Linus Torvalds v minulosti vyjádřil svou nespokojenost s používáním malých polí s proměnnou délkou, protože to generuje nižší kvalitu kódu montáže [6] . Linuxové jádro 4.20 ve skutečnosti neobsahuje pole s proměnnou délkou [ 7] .

Ačkoli C11 výslovně neuvádí limit velikosti pro pole s proměnnou délkou, některé interpretace naznačují, že by měly mít stejnou maximální velikost jako všechny ostatní objekty, tzn. SIZE_MAXbyte [8] . Tuto interpretaci je však nutné chápat v širším kontextu omezení prostředí a platformy, jako je typická velikost stránky s ochranou zásobníku 4 kB, což je o mnoho řádů menší než SIZE_MAX.

Můžete použít syntaxi podobnou poli s proměnnou délkou s dynamickým úložištěm pomocí ukazatele na pole.

float read_and_process ( int n ) { float ( * vals )[ n ] = malloc ( sizeof ( float [ n ])); for ( int i = 0 ; i < n ; ++ i ) ( * vals )[ i ] = read_val (); float ret = proces ( n , * val ); zdarma ( val ); vrátit ret ; }

Ada

Níže je stejný příklad v Ada . Pole obsahují svou délku spolu s daty, takže není potřeba předávat jejich délku funkci Process.

type Vals_Type je pole ( Positive range <>) of Float ; funkce Read_And_Process ( N : Integer ) return Float is Vals : Vals_Type ( 1 .. N ); begin for I in 1 .. N loop Vals ( I ) := Read_Val ; konec -smyčka ; návratový proces ( Vals ); end Read_And_Process ;

Fortran 90

Ekvivalentní funkce v jazyce Fortran 90 .

funkce read_and_process ( n ) result ( o ) integer , intent ( in ) :: n real :: o reálná , dimenze ( n ) :: vals integer :: i do i = 1 , n vals ( i ) = read_val ( ) end do o = proces ( val ) end function read_and_process

Používá funkci Fortran 90 k testování rozhraní procedur v době kompilace; na druhou stranu, pokud funkce používají volací rozhraní před Fortran 90, musí být (externí) funkce deklarovány jako první a délka pole musí být explicitně předána jako argument (jako v C):

funkce read_and_process ( n ) result ( o ) integer , intent ( in ) :: n real :: o real , dimenze ( n ) :: vals real :: read_val , process integer :: i do i = 1 , n vals ( i ) = read_val ( ) end do o = proces ( val , n ) end function read_and_process

Cobol

Následující fragment COBOL deklaruje pole záznamů s proměnnou délkou DEPT-PERSONdélky (počet prvků) dané PEOPLE-CNT:

DIVIZE DAT . PRACOVNĚ-SKLADOVACÍ ČÁST . 01 DEPT-LIDÉ . 05 PEOPLE-CNT PIC S9(4) BINARY . 05 DEPT-PERSON SE VYSKYTUJE 0 20 KRÁT V ZÁVISLOSTI NA LIDECH-CNT . 10 JMÉNO OSOBY OBRÁZEK ​​X(20) . 10 OSOBNÍ MZDA OBR. S9(7)V99 BALENO-DECIMAL .

Pole s proměnnou délkou v COBOL jsou na rozdíl od ostatních zde zmíněných jazyků bezpečná, protože COBOL vyžaduje, abyste zadali maximální velikost pole – v tomto příkladu DEPT-PERSONnemůže obsahovat více než 20 prvků, bez ohledu na hodnotu PEOPLE-CNT.

C#

Následující fragment C# deklaruje pole celých čísel s proměnnou délkou. Před C# 7.2 byl v „nebezpečném“ kontextu vyžadován ukazatel na pole. Klíčové slovo unsafevyžaduje, aby sestavení obsahující tento kód bylo označeno jako nebezpečné.

unsafe void DeclareStackBasedArrayUnsafe ( int size ) { int * pArray = stackalloc int [ size ]; pArray [ 0 ] = 123 ; }

C# verze 7.2 a novější vám umožňuje alokovat pole bez klíčového slova unsafepomocí funkce Span [9] .

void DeclareStackBasedArraySafe ( int size ) { Span < int > stackArray = stackalloc int [ velikost ]; stackArray [ 0 ] = 123 ; }

ObjectPascal

V tomto jazyce se pole s proměnnou délkou nazývá dynamické pole. Deklarování takové proměnné je podobné jako deklarace statického pole, ale bez určení jeho velikosti. Velikost pole je nastavena v době, kdy se používá.

program CreateDynamicArrayOfNumbers ( Size : Integer ) ; var NumberArray : pole LongWord ; _ begin SetLength ( NumberArray , Size ) ; NumberArray [ 0 ] := 2020 ; konec .

Odstranění obsahu dynamického pole se provádí tak, že mu přidělíte velikost nula.

... SetLength ( NumberArray , 0 ) ; ...

Odkazy

  1. 1 2 Pole s proměnnou délkou . Archivováno z originálu 26. ledna 2018.
  2. Variabilní délka – použití GNU Compiler Collection (GCC) .
  3. ISO 9899:2011 Programovací jazyky ​​- C 6.7.6.2 4.
  4. Code Gen Options – GNU Fortran Compiler .
  5. § 6.10.8.3 standardu C11 (n1570.pdf)
  6. LKML: Linus Torvalds: Re: Odstranění VLA (bylo Re: [ lesk RFC 2/2: použijte VLA_SAFE)] . lkml.org .
  7. ↑ Linuxové jádro je nyní bez VLA : Výhra pro bezpečnost, méně režijních nákladů a lepší pro Clang - Phoronix  . www.phoronix.com .
  8. §6.5.3.4 a §7.20.3 standardu C11 (n1570.pdf)
  9. operátor stackalloc (odkaz na C#) . Microsoft.