В компьютерном программировании , A переменной длины массива ( VLA ), называемый также переменного размера или выполнения размера , является массив , длина которого определяется во время выполнения (а не во время компиляции). [1] В C говорят, что VLA имеет изменяемый тип, который зависит от значения (см. Зависимый тип ).
Основная цель VLA - упростить программирование численных алгоритмов.
Языки программирования, поддерживающие VLA, включают Ada , Algol 68 (для негибких строк), APL , C99 (хотя впоследствии они были переведены в C11 в условную функцию, реализация которой не требуется для поддержки; [2] [3] на некоторых платформах, мог быть реализован ранее с помощью alloca()
или аналогичными функциями) и C # (как массивы с выделением стека в небезопасном режиме), COBOL , Fortran 90 , J и Object Pascal (язык, используемый в Borland Delphi и Lazarus, использующий FPC).
объем памяти
Распределение
- В GNU C Compiler выделяет память для Власа с автоматической продолжительностью хранения на стеке . [4] Это более быстрый и простой вариант по сравнению с распределением в куче, и он используется большинством компиляторов.
- VLA также могут быть выделены в куче и доступны изнутри с помощью указателя на этот блок.
Выполнение
C99
Следующая функция C99 выделяет массив переменной длины указанного размера, заполняет его значениями с плавающей запятой и затем передает его другой функции для обработки. Поскольку массив объявлен как автоматическая переменная, его время жизни заканчивается при read_and_process()
возврате.
float read_and_process ( int n ) { float vals [ n ]; для ( int i = 0 ; i < n ; ++ i ) vals [ i ] = read_val (); процесс возврата ( n , vals ); }
В C99 параметр длины должен стоять перед параметром массива переменной длины в вызовах функций. [1] В C11 __STDC_NO_VLA__
макрос определяется, если VLA не поддерживается. [5] GCC имел VLA как расширение до C99.
Линус Торвальдс в прошлом выражал свое недовольство использованием VLA для массивов с заранее определенными небольшими размерами, поскольку он генерирует код сборки более низкого качества. [6] В ядре Linux 4.20 ядро Linux фактически не содержит VLA. [7]
Хотя C11 явно не называет ограничение размера для VLA, некоторые чтения полагают, что он должен иметь такой же максимальный размер, как и все другие объекты, то есть байты SIZE_MAX. [8] Однако это прочтение следует понимать в более широком контексте ограничений среды и платформы, таких как типичный размер страницы защиты стека 4 КиБ, что на много порядков меньше, чем SIZE_MAX.
Ада
Ниже приведен тот же пример на Аде . Массивы Ada несут с собой свои границы, поэтому нет необходимости передавать длину функции Process.
тип Vals_Type является массив ( положительный диапазон <>) от поплавка ;функция Read_And_Process ( N : Integer ) return Float is Vals : Vals_Type ( 1 .. N ); начало для I в 1 .. N петле Vals ( I ) : = Read_Val ; конец петли ; процесс возврата ( Валс ); конец Read_And_Process ;
Фортран 90
Эквивалентная функция Fortran 90 :
функция read_and_process ( n ) результат ( o ) целое число , намерение ( in ) :: n real :: o вещественное , размерность ( n ) :: vals integer :: i do i = 1 , n vals ( i ) = read_val () end do o = process ( vals ) end function read_and_process
при использовании функции Fortran 90 проверки интерфейсов процедур во время компиляции; с другой стороны, если функции используют интерфейс вызова до Fortran 90, (внешние) функции должны быть сначала объявлены, а длина массива должна быть явно передана в качестве аргумента (как в C):
функция read_and_process ( n ) результат ( o ) целое число , намерение ( in ) :: n real :: o вещественное , измерение ( n ) :: vals real :: read_val , целое число процесса :: i do i = 1 , n vals ( i ) = read_val () end do o = process ( vals , n ) end function read_and_process
Кобол
Следующий фрагмент COBOL объявляет массив записей переменной длины DEPT-PERSON
, длина (количество членов) которых определяется значением PEOPLE-CNT
:
ОТДЕЛЕНИЕ ДАННЫХ . РАБОЧАЯ-STORAGE РАЗДЕЛ . 01 ОТДЕЛЕНИЕ-ЛЮДИ . 05 PEOPLE-CNT PIC S9 (4) ДВОИЧНЫЙ . 05 DEPT-ЛицО OCCURS 0 TO 20 РАЗ ЗАВИСИМОСТИ НА ЛЮДИ-НКТ . 10 ЛИЦО, ФОТО X (20) . 10 человеко-ЗАРАБОТНОЙ ПОС S9 (7) V99 УПАКОВАННЫЕ-числовом .
COBOL VLA, в отличие от других языков , упомянутых здесь, является безопасным , так как COBOL требует, чтобы указать размер массива максимальный - в этом примере, DEPT-PERSON
не может иметь более 20 пунктов, независимо от стоимости PEOPLE-CNT
.
C #
В следующем фрагменте C # объявляется массив целых чисел переменной длины. До версии C # 7.2 требовался указатель на массив, требующий «небезопасного» контекста. Ключевое слово unsafe требует, чтобы сборка, содержащая этот код, была помечена как небезопасная.
unsafe void DeclareStackBasedArrayUnsafe ( int size ) { int * pArray = stackalloc int [ size ]; pArray [ 0 ] = 123 ; }
C # версии 7.2 и более поздних версий позволяет выделять массив без ключевого слова «unsafe» с помощью функции Span. [9]
void DeclareStackBasedArraySafe ( int size ) { Span < int > stackArray = stackalloc int [ size ]; stackArray [ 0 ] = 123 ; }
Object Pascal
На этом языке он называется динамическим массивом. Объявление такой переменной аналогично объявлению статического массива, но без указания его размера. Размер массива указывается на момент его использования.
программа CreateDynamicArrayOfNumbers ( Size : Integer ) ; вар NumberArray : массив из LongWord ; begin SetLength ( NumberArray , Size ) ; NumberArray [ 0 ] : = 2020 ; конец .
Удаление содержимого динамического массива выполняется путем присвоения ему нулевого размера.
... SetLength ( NumberArray , 0 ) ; ...
Рекомендации
- ^ a b «Массивы переменной длины» . Архивировано из оригинала на 2018-01-26. CS1 maint: обескураженный параметр ( ссылка )
- ^ «Переменная длина - Использование коллекции компиляторов GNU (GCC)» .
- ^ ISO 9899: 2011 Языки программирования - C 6.7.6.2 4.
- ^ «Параметры генерации кода - компилятор GNU Fortran» .
- ^ § 6.10.8.3 стандарта C11 (n1570.pdf)
- ^ «LKML: Линус Торвальдс: Re: удаление VLA (было Re: [RFC 2/2] lustre: use VLA_SAFE)» . lkml.org .
- ^ «Ядро Linux теперь не содержит VLA: выигрыш по безопасности, меньше накладных расходов и лучше для Clang - Phoronix» . www.phoronix.com .
- ^ §6.5.3.4 и §7.20.3 стандарта C11 (n1570.pdf)
- ^ «Оператор stackalloc (справочник по C #)» . Microsoft.