Можно определить размер массива во время выполнения в c?

Как я знаю, массив должен иметь определенный размер перед компиляцией времени в c.

Интересно, почему этот код все еще работает?

int s;
printf("enter the array size: ");
scanf("%d",&s);

int a[s]; // Isn't s value determined at run time?

Ответ 1

Размеры массива должны быть известны с помощью ANSI 89 C. Версия спецификации 99 устранила это ограничение и разрешила массивы с переменным размером.

В документации нет версии GNU этой функции

Ответ 2

Если вам нужно выделить массив с динамическим размером, вы должны получить его из кучи с помощью malloc().

int *a = (int*)malloc(sizeof(int) * s)

Ответ 3

Этот код поддерживается спецификацией языка C99. Этот код также поддерживается компилятором GCC в режиме C89/90 в качестве расширения.

Итак, ответ на ваш вопрос (почему он "работает" ) зависит от того, как вы его компилируете. В общем случае это даже не компилируется компилятором C89/90.

Ответ 4

Здесь вы смешиваете две вещи.

1) Определение размера уже выделенного массива (что подразумевает ваш заголовок): разделите sizeof() на общий размер на один (скажем, первый) элемент:

 sizeof(a)/sizeof(a[0])

2) Динамическое выделение памяти по вашему запросу:

 int *a = (int*)malloc( s * sizeof(int) );

Ответ 5

Важно понять, как память распределена переменной компилятором, чтобы дать правильный ответ на ваш вопрос. Существует два режима, в которых память назначается переменной, она может находиться в куче или может находиться в стеке. Память в куче выделяется динамически. Таким образом, переменной, которая выделяется память в куче, может быть задан ее размер во время выполнения.

Массивы в случае C задаются памятью в стеке. Для обеспечения памяти в стеке размер памяти должен быть известен компилятору во время компиляции. Так что во время выполнения много памяти может быть выделено для переменной в стеке. Именно по этой причине вы не можете определить размер массива во время выполнения до языка C.

Ответ 6

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);