6.20 Массивы переменной длины
Массивы с автоматическим выделением памяти переменной длины разрешены в ISO C99, а как расширение GCC принимает их в режиме C90 и в C++. Эти массивы объявляются как любые другие автоматические массивы, но с длиной, которая не является константным выражением. Память выделяется в момент объявления и освобождается, когда область видимости блока, содержащего объявление, завершается. Например:
FILE *
concat_fopen (char *s1, char *s2, char *mode)
{
char str[strlen (s1) + strlen (s2) + 1];
strcpy (str, s1);
strcat (str, s2);
return fopen (str, mode);
}
Выход из области видимости имени массива (путем перехода или прерывания) освобождает выделенную память. Вход в область видимости не разрешен; за это вы получите сообщение об ошибке.
В качестве расширения GCC принимает массивы переменной длины как члены структуры или объединения. Например:
void
foo (int n)
{
struct S { int x[n]; };
}
Вы можете использовать функцию alloca для получения эффекта, очень похожего на массивы переменной длины. Функция alloca доступна во многих других реализациях C (но не во всех). С другой стороны, массивы переменной длины более элегантны.
Существуют и другие различия между этими двумя методами. Память, выделенная с помощью alloca, существует до тех пор, пока не вернётся содержащая функция. Память для массива переменной длины освобождается сразу же, как только заканчивается область видимости имени массива, если вы также не используете alloca в этой области видимости.
Вы также можете использовать массивы переменной длины в качестве аргументов функциям:
struct entry
tester (int len, char data[len][len])
{
/* … */
}
Длина массива вычисляется один раз при выделении памяти и запоминается для области видимости массива, в случае если вы обращаетесь к ней с помощью sizeof.
Если вы хотите передать массив сначала, а затем длину, вы можете использовать объявление вперёд в списке параметров — ещё одно расширение GNU.
struct entry
tester (int len; char data[len][len], int len)
{
/* … */
}
«int len» перед точкой с запятой является параметрическим объявлением вперёд, и оно служит для того, чтобы имя len стало известным при разборе объявления data.
В списке параметров можно записать любое количество таких параметрических объявлений вперёд. Они могут быть разделены запятыми или точками с запятой, но последнее должно заканчиваться точкой с запятой, за которой следуют «реальные» объявления параметров. Каждое объявление вперёд должно соответствовать «реальному» объявлению по имени параметра и типу данных. ISO C99 не поддерживает параметрические объявления вперёд.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-13.3.0/gcc/Variable-Length.html