Возможный дубликат:
Изменяемый массив в области видимости файла
У меня есть некоторые понятия о VLA и его поведение, которое мне нужно уточнить.
AFIK начиная с C99, можно объявить VLA в локальных областях:
int main(int argc, char **argv)
{
// function 'main' scope
int size = 100;
int array[size];
return 0;
}
Но это запрещено в глобальных областях:
const int global_size = 100;
int global_array[global_size]; // forbidden in C99, allowed in C++
int main(int argc, char **argv)
{
int local_size = 100;
int local_array[local_size];
return 0;
}
Код выше объявляет VLA в C99, потому что const
Модификатор не создает значение времени компиляции. В C ++ global_size
это значение времени компиляции так, global_array
не становится VLA.
Что мне нужно знать, так это: правильны ли мои рассуждения? Поведение, которое я описал, правильно?
Я также хочу знать: почему VLA в глобальном масштабе не разрешены? запрещены как в C, так и в C ++? Какая причина для того, чтобы поведение массивов в глобальном и локальном контексте было разным?
Да, ваши рассуждения верны, именно так C и C ++ рассматривают эти различные формы объявлений и определений массивов.
Как уже говорилось, VLA с переменной длиной (неconst
) в глобальном масштабе трудно понять. Каков будет порядок оценки, например, если выражение длины будет ссылаться на объект другой единицы компиляции? C ++ не имеет VLA, но имеет динамическую инициализацию объектов в области видимости файла. И уже это вызывает головную боль, если вам приходится полагаться на порядок оценки.
Это оставляет небольшой пробел для C относительно выражений длины, которые содержат const
квалифицированный объект, который не допускается. Это происходит из-за того, что такие объекты не рассматриваются как «целочисленные константные выражения» в стандарте C. Возможно, это изменится в будущих версиях, но до сих пор комитет C не считал необходимым допускать такую вещь: enum
Константы, которые играют эту роль в C. Их единственным ограничением является то, что они ограничены int
в С было бы неплохо иметь их size_t
,
C ++ не поддерживает VLA, точка. Причина, по которой второй фрагмент кода работает в C ++, заключается в том, что const
ключевое слово создает постоянную времени компиляции в C ++; в С это не так.
C99 не поддерживает VLA вне области блока, точка, независимо от того, как вы объявляете переменную размера. Обратите внимание, что C2011 делает поддержку VLA необязательной.
Я думаю, что фундаментальная причина в том, что глобальная переменная имеет связь, ее размер должен быть известен во время компиляции. Если нет, то как можно связать программу?
локальные переменные не имеют никакой связи, и VLA размещаются в стеке, который динамически увеличивается по мере выполнения программы.
Существует разница между запретом и недопущением. 😉
Функция VLA предназначена для использования стекового пространства для локального массива, чтобы избежать использования malloc для выделения кучи. Это в основном оптимизация скорости.
Теперь вы хотите использовать VLA вне функций. Зачем? Скоро выиграть не так много, чтобы избежать одиночного вызова malloc во время запуска программы. И какое пространство стека мы должны использовать для переменных со статическим временем жизни?
Итак, для глобальных VLA один из вопросов (есть много вариантов по теме) может быть показан здесь:
int size;
int a;
int v[size];
int b;
….
в другом файле:
extern int a;
extern int b;
Компоновщик должен знать, где находятся a и be по отношению друг к другу во время соединения, или он не сможет правильно их исправить во время загрузки.