В C, const
следует читать как только для чтения. Он не определяет время компиляции.
const int a = 5;
Здесь a
, является не постоянным выражением в соответствии с требованиями C standard:
6.7.9 Инициализация
4 Все выражения в инициализатора для объекта, который имеет статический или нить длительность хранения должна быть постоянной выражениями или строковыми литералами.
Таким образом, ошибка указывает, что вы используете компилятор C89/C90. Вы можете прочитать ввод от пользователя для a
и объявить variable length array, который является C99-функцией, которая имеет автоматическую продолжительность хранения.
Использование #define
- это еще один способ. Но это просто текстовая замена и определяет массив с автоматическим временем хранения. Это то же самое, что и определение int arr[5];
.
Если вы хотите выделить память в динамическом хранилище (обычно называемое «кучей»), вы должны использовать malloc()
семейные функции, которые будут иметь жизненный цикл без выполнения программы, пока вы не назовете на нее free()
.
(Обратите внимание, что это поведение const
только в C. C++ отличается этим и будет работать так, как вы ожидали).
Если я скомпилировать код в C89, он терпит неудачу с:
#include <stdio.h>
int main(){
const int a = 5;
int i;
int arr [a];
for (i = 0; i < 5; i++) {
arr[i] = i * 2;
}
printf("%d", arr[1]);
return 0;
}
$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c
test.c: In function âmainâ:
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla]
int arr [a];
^
потому, что C89 не поддерживает Власа (Хотя GCC поддерживает как an extension даже в C89/C90). Поэтому, если вы используете компилятор, который не поддерживает C99, вы не можете использовать VLA. Например, визуальная студия не полностью поддерживает все функции C99 и C11. Хотя, Visual studio 2015 support most C99 features, VLA не являются одним из них.
Но тот же код компилируется в C99 и C11 без каких-либо проблем:
$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
Это потому, что были добавлены массивы переменной длины (Vlas) в C99. Обратите внимание, что VLA стали дополнительными в стандарте C11. Таким образом, реализация не может поддерживать VLA в C11. Вам необходимо протестировать против __STDC_NO_VLA__
, чтобы проверить, не поддерживает ли VLA вашу реализацию.
От 6.10.8.3 Conditional feature macros
__STDC_NO_VLA__
Целого числа константы 1, предназначено для указания того, что реализация не поддерживает массивы переменной длины или переменно модифицированных типов.
Я лично не использую VLA, так как отказ распределения не может быть портативно найден, если размер массива достаточно велик. Например.
size_t size = 8*1024;
int arr[size];
В приведенном выше фрагменте, если arr
распределение не удалось, вы не будете знать его до времени выполнения. Что такое «достаточно маленький» размер, для которого распределение памяти зависит от платформы. Таким образом, на одной машине распределение 1 МБ может преуспеть, а другое - потерпеть неудачу, а худшая часть состоит в том, что не удается поймать этот сбой.
Таким образом, использование VLA ограничено и может использоваться только с небольшими массивами, которые, как вы знаете, всегда будут успешными на данной платформе. Но в этом я бы просто запрограммировал размер массива и позаботился о граничных условиях.
Ваше утверждение о том, что доступные альтернативы в основном или '# define' или' malloc' верное - выберите один из этих двух вариантов, чтобы исправить это. Ответ, сделанный l3x, хорошо объясняет, почему. – GrandOpener