Вообще-то изначально в C такой возможности не было. И добавлена в язык она была достаточно поздно.
В языке C вообще нет массивов - в том смысле, какой вкладывается в это понятие в языках высокого уровня. Есть лишь бесконтрольная арифметика указателей и несколько механизмов выделения участка памяти требуемого размера. Предельная эффективность скомпилированного кода, за которую приходится расплачиваться предельной низкоуровневостью - почти на уровне ассемблера.
Тогда как в С++ полноценные массивы есть: в виде стандартных обобщённых типов array и vector. Наличие полноценных динамических массивов (в виде типа vector) делает бессмысленным введение в язык примитивных суррогатов динамических массивов в виде неконстантных выражений.
Это VLA — массивы переменной длины. В язык C они были добавлены в стандарте C99, тогда как в C++ от них намеренно отказались, поскольку они вызывают массу проблем. Стандартная библиотека языка C++ в качестве альтернативы предлагает контейнеры, такие как std::vector.
Потому что в C++ есть более совершенный вид массивов - vector, и нужды в таких массивах нет. Впрочем, многие компиляторы позволяют такие массивы как расширение языка, но в стандарте C++ таких массивов нет.
В C и C++ есть принципиальные отличия в том, как они обрабатывают объявление массивов с неконстантным размером:
В C:
* Размер массива может быть определен во время выполнения: В C размер массива может быть задан переменной, значение которой может быть определено во время выполнения (например, с помощью пользовательского ввода). Это связано с тем, что C компилирует код не так строго, как C++, и позволяет размещать массивы на стеке.
* Это может привести к ошибкам: Однако, если размер массива определяется неконстантным выражением, то компилятор не может проверить, чтобы размер был неотрицательным и не превышал лимитов памяти. Это может привести к ошибкам во время выполнения, таким как выход за границы массива или ошибка сегментации.
В C++:
* Размер массива должен быть константным выражением: В C++ размер массива должен быть определен с помощью константного выражения, то есть значения, которое может быть вычислено во время компиляции. Это сделано для того, чтобы гарантировать, что размер массива всегда известен во время компиляции, и компилятор может проверить корректность выделения памяти.
* Использование `std::vector` для динамических массивов: В C++ для создания массивов, размер которых определяется во время выполнения, используется контейнер `std::vector`. Он предоставляет функциональность для динамического изменения размера и является более безопасным вариантом, так как автоматически управляет памятью.
Причина различий:
* Историческая: В C был выбран такой подход, чтобы обеспечить большую гибкость, но это также создавало больше возможностей для ошибок.
* Безопасность: В C++ был добавлен этот ограничитель для повышения безопасности кода и предотвращения распространенных ошибок, связанных с массивами.
Рекомендации:
* Используйте `std::vector` в C++: В C++ для динамических массивов лучше использовать `std::vector`, так как он предоставляет функции для безопасного управления памятью.
* В C будьте осторожны с неконстантным размером массивов: Если вы используете неконстантный размер массива в C, убедитесь, что он неотрицательный и не превышает лимитов памяти.
* Рассмотрите возможность использования `alloca` для выделения памяти на стеке: В C можно использовать функцию `alloca` для выделения памяти на стеке, что позволяет создавать массивы с размером, определенным во время выполнения. Однако, важно понимать, что эта функция не всегда безопасна и может привести к ошибкам.
В целом, использование константного размера для массивов в C++ является более безопасным и рекомендованным подходом