распределенный массив VS. массив переменной длины

Существует два способа выделения памяти массиву, размер которого изначально неизвестен. Самый распространенный способ - использовать malloc вот так

int * array;
... // when we know the size
array = malloc(size*sizeof(int));

Но в C99 также допустимо определять массив после того, как мы знаем его размер.

... // when we know the size
int array[size];

Они абсолютно одинаковы?


person linusz    schedule 21.05.2013    source источник
comment
Второй, даже в C99, НЕ всегда действителен. Согласно C99 §6.10.8.3 Макросы условных функций, реализация может определять _STDC_NO_VLA_ и не реализовывать массивы переменной длины. , и по-прежнему соответствовать стандартам.   -  person WhozCraig    schedule 21.05.2013
comment
Это не повторяющийся вопрос! Ни в одном из упомянутых вопросов нет подробностей о различиях.   -  person Jens    schedule 21.05.2013
comment
@WhozCraig Насколько я знаю, это вещь 2011 года. В том, что у меня есть, нет такого раздела, который претендует на то, чтобы быть копией стандарта C99.   -  person Daniel Fischer    schedule 21.05.2013
comment
@DanielFischer Страница 176, черновик 1548, последний, который у меня есть, ISO / IEC 9899: 201x, и он там. Вы хотите сказать, что его вырезали из финальной версии? (или вы имеете в виду 201x, что теперь имеет больше смысла, когда я думаю об этом).   -  person WhozCraig    schedule 21.05.2013
comment
@WhozCraig Это рабочий проект стандарта 2011 года. VLA необязательны в том смысле, что их не было в версии 1999 года. Этого раздела еще не было в C99, он был добавлен где-то за 12 лет между стандартами. (И на всякий случай здесь последний проект перед ратификацией.)   -  person Daniel Fischer    schedule 21.05.2013
comment
@DanielFischer спасибо за ссылку и пояснение, сэр. Я не проживаю ни дня, чтобы не узнать что-то новое.   -  person WhozCraig    schedule 22.05.2013


Ответы (1)


Нет, они не абсолютно одинаковы. Хотя оба позволяют хранить одинаковое количество и тип объектов, имейте в виду, что:

  • Вы можете free() использовать распределенный массив, но вы не можете free() массив переменной длины (хотя он выходит за пределы области видимости и перестает существовать, как только закрывающий блок остается). Говоря техническим жаргоном, они имеют разную длительность хранения: выделено для malloc и автоматически для массивов переменной длины.
  • Хотя в C нет концепции стека, многие реализации выделяют массив переменной длины из стека, а malloc — из кучи. Это проблема в системах с ограниченным стеком, например. многие встроенные операционные системы, где размер стека порядка КБ, а куча гораздо больше.
  • Также легче проверить неудачное выделение с помощью malloc, чем с массивом переменной длины.
  • распределенная память может быть изменена по размеру с помощью realloc(), в то время как VLA не могут (точнее, только путем повторного выполнения блока с другим размером массива, который теряет предыдущее содержимое).
  • Размещенная реализация C89 поддерживает только malloc().
  • Размещенная реализация C11 может не поддерживать массивы переменной длины (тогда она должна определить __STDC_NO_VLA__ как целое число 1 в соответствии с C11 6.10.8.3).
  • Все остальное я пропустил :-)
person Jens    schedule 21.05.2013
comment
VLA выходит из области видимости (перестает быть видимой) в конце окружающего блока, потому что имеет блочную область действия. Он перестает существовать в конце блока, потому что он имеет автоматическую продолжительность хранения. Две разные вещи. - person Keith Thompson; 21.05.2013
comment
@KeithThompson Спасибо за подсказку по терминологии; Я отредактировал ответ, чтобы он был более точным. - person Jens; 21.05.2013
comment
@KeithThompson: Чтобы быть точным, идентификатор массива выходит за рамки в конце окружающих блоков. Области — это свойства идентификаторов (имен), а не объектов. Объект может быть доступен за пределами его идентификатора, например, когда его адрес передается другой процедуре. - person Eric Postpischil; 21.05.2013
comment
@EricPostpischil: Ты превзошел меня! - person Keith Thompson; 21.05.2013
comment
@Jens Что именно вы подразумеваете под C не имеет понятия стека? Впервые слышу об этом и очень заинтригован. Не могли бы вы уточнить? - person stillanoob; 21.08.2018
comment
@ibrahim5253 ibrahim5253 Это означает, что слово стек не встречается в стандартных документах языка ISO C. C не зависит от стека. - person Jens; 21.08.2018
comment
что, если VLA инициализируется в глобальной области видимости? Умирает, что означает, что он выйдет из области видимости, когда main() выйдет? - person Daniel; 21.06.2020
comment
@Daniel C не разрешает использование VLA в области файлов. Вы также не можете иметь static VLA в области блока. - person Jens; 21.06.2020
comment
@Jens спасибо. Я сам только изучаю C и был смущен глобальной областью действия. То есть, поскольку main() является точкой входа и выхода программы(?) , переменная, объявленная внутри тела main, имеет локальную область видимости, поскольку она находится внутри функции, но ее продолжительность будет с момента ее объявления до... конец программы, т.е. до выхода из main, верно? (при условии, что он не вложен в другой блок) - person Daniel; 22.06.2020
comment
@Daniel main() — это вход, но может и не быть выходом. Другими функциями для завершения программы являются exit(), quick_exit(), _Exit() и abort(). - person Jens; 22.06.2020