WikiDer > Массив переменной длины
В компьютерное программирование, а массив переменной длины (VLA), также называется переменный размер или размер во время выполнения, является структура данных массива длина которого определяется во время выполнения (а не во время компиляции).[1]В языке C говорят, что VLA имеет переменно модифицированный тип это зависит от значения (см. Зависимый тип).
Основное назначение VLA - упрощение программирования численных алгоритмов.
Языки программирования, поддерживающие VLA, включают: Ада, Алгол 68 (для негибких строк), APL, C99 (хотя впоследствии был переведен в C11 к условной функции, реализация которой не обязательна для поддержки;[2][3] на некоторых платформах, ранее могла быть реализована с alloca()
или аналогичные функции) и C # (как массивы, размещенные в стеке в небезопасном режиме), КОБОЛ, Фортран 90, J, и Object Pascal (язык, используемый в Borland Delphi и Lazarus, использующий FPC).
объем памяти
Размещение
- В Компилятор GNU C выделяет память для VLA с автоматическая продолжительность хранения на стек.[4] Это более быстрый и простой вариант по сравнению с распределением в куче, и он используется большинством компиляторов.
- VLA также могут быть размещены на куча и внутренний доступ с использованием указателя на этот блок.
Реализация
C99
Следующее C99 Функция выделяет массив переменной длины заданного размера, заполняет его значениями с плавающей запятой, а затем передает его другой функции для обработки. Поскольку массив объявлен как автоматическая переменная, его время жизни заканчивается, когда read_and_process ()
возвращается.
плавать read_and_process(int п){ плавать вальс[п]; для (int я = 0; я < п; ++я) вальс[я] = read_val(); вернуть обработать(п, вальс);}
В C99 параметр длины должен стоять перед параметром массива переменной длины в вызовах функций.[1] В C11 a __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 : Целое число) вернуть Плавать является Вальс : Vals_Type (1 .. N);начать для я в 1 .. N петля Вальс (я) := Read_Val; конец петля; вернуть Обработать (Вальс);конец Read_And_Process;
Фортран 90
Эквивалент Фортран 90 функция
функция read_and_process(п) результат(о) целое число,намерение(в)::п настоящий::о настоящий,измерение(п)::вальс целое число::я делать я = 1,п вальс(я) = read_val() конец делатьо = обработать(вальс)конечная функция read_and_process
при использовании функции Fortran 90 проверки интерфейсов процедур во время компиляции; с другой стороны, если функции используют интерфейс вызова до Fortran 90, (внешние) функции должны быть сначала объявлены, а длина массива должна быть явно передана в качестве аргумента (как в C):
функция read_and_process(п) результат(о) целое число,намерение(в)::п настоящий::о настоящий,измерение(п)::вальс настоящий::read_val, обработать целое число::я делать я = 1,п вальс(я) = read_val() конец делатьо = обработать(вальс,п)конечная функция read_and_process
Кобол
Следующее КОБОЛ фрагмент объявляет массив записей переменной длины ОТДЕЛЕНИЕ
имеющий длину (количество членов), заданную значением ЛЮДИ-CNT
:
ДАННЫЕ ОТДЕЛЕНИЕ.РАБОТА-ХРАНЕНИЕ РАЗДЕЛ.01 ДЕПТ-ЛЮДИ. 05 ЛЮДИ-CNT ПИК S9 (4) БИНАРНЫЙ. 05 ОТДЕЛЕНИЕ ПРОИСХОДИТ 0 К 20 ВРЕМЯ В ЗАВИСИМОСТИ НА ЛЮДИ-CNT. 10 ЛИЦО ПИК X (20). 10 ЧЕЛОВЕК-ЗАРПЛАТА ПИК S9 (7) V99 УПАКОВАННЫЙ-ДЕСЯТИЧНЫЙ.
В КОБОЛ VLA, в отличие от других языков, упомянутых здесь, безопасен, потому что КОБОЛ требуется указать максимальный размер массива - в этом примере ОТДЕЛЕНИЕ
не может быть больше 20 предметов, независимо от стоимости ЛЮДИ-CNT
.
C #
Следующее C # fragment объявляет массив целых чисел переменной длины. До версии C # 7.2 требовался указатель на массив, требующий «небезопасного» контекста. Ключевое слово «unsafe» требует, чтобы сборка, содержащая этот код, была помечена как небезопасная.
небезопасно пустота DeclareStackBasedArrayUnsafe(int размер){ int *pArray = stackalloc int[размер]; pArray[0] = 123;}
C # версии 7.2 и более поздних версий позволяет выделять массив без ключевого слова «unsafe» за счет использования функции Span.[9]
пустота DeclareStackBasedArraySafe(int размер){ Span<int> stackArray = stackalloc int[размер]; stackArray[0] = 123;}
Object Pascal
На этом языке он называется динамическим массивом. Объявление такой переменной аналогично объявлению статического массива, но без указания его размера. Размер массива указывается на момент его использования.
программа CreateDynamicArrayOfNumbers(Размер: Целое число);вар NumberArray: массив из LongWord;начать SetLength(NumberArray, Размер); NumberArray[0] := 2020;конец.
Удаление содержимого динамического массива выполняется путем присвоения ему нулевого размера.
...SetLength(NumberArray, 0);...
использованная литература
- ^ а б «Массивы переменной длины». Архивировано из оригинал на 2018-01-26.
- ^ «Переменная длина - Использование коллекции компиляторов 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.