Как я знаю, массив должен иметь определенный размер перед компиляцией времени в c.
Интересно, почему этот код все еще работает?
int s;
printf("enter the array size: ");
scanf("%d",&s);
int a[s]; // Isn't s value determined at run time?
Как я знаю, массив должен иметь определенный размер перед компиляцией времени в c.
Интересно, почему этот код все еще работает?
int s;
printf("enter the array size: ");
scanf("%d",&s);
int a[s]; // Isn't s value determined at run time?
Размеры массива должны быть известны с помощью ANSI 89 C. Версия спецификации 99 устранила это ограничение и разрешила массивы с переменным размером.
В документации нет версии GNU этой функции
Если вам нужно выделить массив с динамическим размером, вы должны получить его из кучи с помощью malloc().
int *a = (int*)malloc(sizeof(int) * s)
Этот код поддерживается спецификацией языка C99. Этот код также поддерживается компилятором GCC в режиме C89/90 в качестве расширения.
Итак, ответ на ваш вопрос (почему он "работает" ) зависит от того, как вы его компилируете. В общем случае это даже не компилируется компилятором C89/90.
Здесь вы смешиваете две вещи.
1) Определение размера уже выделенного массива (что подразумевает ваш заголовок): разделите sizeof()
на общий размер на один (скажем, первый) элемент:
sizeof(a)/sizeof(a[0])
2) Динамическое выделение памяти по вашему запросу:
int *a = (int*)malloc( s * sizeof(int) );
Важно понять, как память распределена переменной компилятором, чтобы дать правильный ответ на ваш вопрос. Существует два режима, в которых память назначается переменной, она может находиться в куче или может находиться в стеке. Память в куче выделяется динамически. Таким образом, переменной, которая выделяется память в куче, может быть задан ее размер во время выполнения.
Массивы в случае C задаются памятью в стеке. Для обеспечения памяти в стеке размер памяти должен быть известен компилятору во время компиляции. Так что во время выполнения много памяти может быть выделено для переменной в стеке. Именно по этой причине вы не можете определить размер массива во время выполнения до языка C.
Variable Length Arrays были частью языка C, поскольку C99. Но они были сделаны как функция в C11 - это означает, что соответствующая реализация C11 не должна ее предоставлять (хотя практически вся реализация, которая поддержка C99, безусловно, обеспечивает VLA в C11).
Вы можете проверить, не реализует ли реализация VLA макрос __STDC_NO_VLA__
(если он определен в режиме компиляции C99 или C11, то ваша реализация не поддерживает VLA).
Так что выбор размера массива во время выполнения возможен в современном C ( >= C99), и код, подобный приведенному ниже, хорош:
int s;
printf("Enter the array size: ");
scanf("%d", &s);
int a[s];
Один очевидный недостаток VLA заключается в том, что если s
достаточно велико, а выделение a
coud терпит неудачу. Хуже того, нет способа проверить, не было ли выделение, и вы столкнетесь с ошибками во время выполнения (например, segfault). Это существенно undefined поведение. Поэтому вы хотите избежать VLA, если размер массива слишком большой. В основном,
когда вы сомневаетесь, перейдите для динамического распределения памяти (см. ниже).
Другая проблема, гораздо менее серьезная по сравнению с другими, с VLA заключается в том, что они имеют автоматическую продолжительность хранения (ака "выделение стека" ). Поэтому, если вы хотите что-то, что длится дольше, чем область, в которой объявляется VLA, тогда VLA не помогают.
В C89 нет VLA. Таким образом, использование динамического распределения памяти является единственным способом. Хотя, были некоторые нестандартные расширения, такие как alloca()
, который похож на VLA и имеет те же недостатки, что и VLA).
int s;
printf("enter the array size: ");
scanf("%d",&s);
int *a = malloc(s * sizeof *a);
...
free(a);