Согласно правильному ответу в Статический массив против динамического массива в C ++ статические массивы имеют фиксированные размеры.
Тем не менее, это компилируется и работает просто отлично:
int main(int argc, char** argv)
Означает ли это, что размер статического массива можно изменить?
Решение
Вы на самом деле не увеличиваете массив. Давайте посмотрим ваш код подробно:
int myArray[2]; myArray[0] = 0; myArray[1] = 1;
Вы создаете массив из двух позиций с индексами от 0 до 1. Пока все хорошо.
myArray[4];
Вы получаете доступ к пятому элементу в массиве (элемент, который, безусловно, не существует в массиве). Это неопределенное поведение: все может случиться. Вы ничего не делаете с этим элементом, но это не важно.
myArray[2] = 2; myArray[3] = 3;
Теперь вы получаете доступ к элементам три и четыре и меняете их значения. Опять же, это неопределенное поведение. Вы меняете ячейки памяти рядом с созданным массивом, но «больше ничего». Массив остается прежним.
Массив объектов класса. Динамический. Статический. Создание Особенности. ООП C++ Для начинающих #96
На самом деле, вы можете проверить размер массива, выполнив:
std::cout
Вы проверите, что размер массива не изменился. Кстати, этот прием работает в той же функции, в которой объявлен массив, как только вы передаете его, он распадается в указатель.
В C ++ границы массивов не проверяются. Вы не получили ни ошибки, ни предупреждения в основном из-за этого. Но опять же, доступ к элементам за пределами массива является неопределенным поведением. Неопределенное поведение означает, что это ошибка, которая может появиться не сразу. Даже программа, очевидно, может закончиться без проблем.
Надеюсь это поможет.
Другие решения
Нет, в аду нет шансов. Все, что вы сделали, — это незаконный доступ к нему за его пределами. Тот факт, что это не приводит к ошибке для вас, совершенно не имеет значения. Это полностью UB.
Во-первых, это не статический массив, это массив, выделенный в автоматическое хранение.
myArray[4];
не является новым объявлением, это отброшенное чтение из элемента # 4 ранее объявленного двухэлементного массива — неопределенное поведение.
Задания, которые следуют
myArray[2] = 2; myArray[3] = 3;
запись в память, которая не выделена для вашей программы — также неопределенное поведение.
Источник: web-answers.ru
Статический массив. Структура, его преимущества и недостатки
Задание размера статического массива run-time значением
К чему может привести, или вообще ни к чему не приведёт, задание размера статического массива значением, которое станет известно лишь на этапе выполнения программы? Знаю лишь то, что это не по стандарту языка C++ , в C это вполне себе законно. Примером будет выступать вот такой код:
int main() < int n; std::cin >> n; T arr[n]; /*код, включающий в себя работу с массивом arr*/ return 0; >
Отслеживать
user206435
задан 24 окт 2019 в 21:02
157 7 7 бронзовых знаков
В си это не законно, это просто расширения компиляторов которые позволяют так делать. С GCC этот код компилируется, однако не под всеми версиями, а компилятор от майкрософт, честно вам отдаст ошибку. Для C++ есть вектор, которому вы можете прямо во время выполнения менять размер, при помощи метода resize .
MQL4 программирование — Массивы и циклы
– user206435
24 окт 2019 в 21:35
Вектора использовать умею. Дело в том, что на недавнем уроке информатики моему классу рассказывали о том, что не пишите так, мол, программа даже если компилируется, то будет работать неправильно. Я возразил, что это лишь будет код, написанный в несогласовании со стандартом языка, т.к. такое утверждение встречал когда-то на этом сайте. Кстати, в мой лицей один человек не попал лишь из-за того, что в письменном экзамене по информатике он написал стат. массив с длиной, вводимой с клавиатуры :). Ещё один вопрос: если всё таки скомпилировалась, то работать будет без никаких undefined behaviour?
24 окт 2019 в 21:50
24 окт 2019 в 22:16
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
В языке С++ такие массивы не поддерживаются
В типичной традиционной реализации VLA в языке C определение локального VLA
T arr[n];
будет втихаря заменено компилятором на два определения локальных переменных
size_t __size_arr; T *arr;
Размер массива будет сохранен во внутренней переменной __size_arr
size_t __size_arr = n;
(то есть таким образом будет запомнено, каким было значение n в тот момент, когда управление проходило по вашему объявлению).
А память для самого массива будет выделена на вершине стека при помощи некоей внутренней платформенно-зависимой функциональности вроде alloca
T *arr = alloca(__size_arr * sizeof(T));
Также, в точке(-ах) выхода из блока, содержащего определение такого массива (таких массивов), компилятор сгенерирует код, возвращающий вершину стека в то положение, в котором она находилась при входе в этот блок, т.е. фактически освобождающий весь стек, выделенный для VLA в этом блоке.
Вычисление размера такого массива через sizeof arr будет порождать выражение вида
__size_arr * sizeof(T)
значение которого будет вычисляться во время выполнения. Если аргумент такого sizeof имеет побочные эффекты, то они возымеют место во время выполнения
unsigned n = 42; unsigned a[n]; unsigned s = sizeof(*(printf(«Hello Worldn»), // Напечатает «Hello World»
Также, по понятным причинам, компилятор не позволит вам передавать управление ( goto или switch ) в области видимости таких массивов через объявления таких массивов и объявления соответствующих типов
goto skip; // Ошибка: нелегальный `goto` unsigned n = 42; unsigned a[n]; skip:;
Также, язык накладывает определенные ограничения на использование стандартных функций setjmp / longjmp в присутствии VLA.
Источник: ru.stackoverflow.com