6.2.1 Массивы переменной длины
Автоматические массивы переменной длины разрешены в 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);
}
Переход за пределы области видимости имени массива или выход из неё с помощью оператора break освобождает память. Переход внутрь этой области не разрешён; в этом случае вы получите сообщение об ошибке.
В качестве расширения 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-15.3.0/gcc/Variable-Length.html