В Стандарте С99 появились два новых для С и достаточно важных свойства массивов: переменная длина и возможность включать в объявлениях массивов квалификаторы типа.
Массивы переменной длины
В С89 размерности массивов необходимо объявлять при помощи выражений из целых констант, причем размер массива фиксируется во время компиляции. В силу определенных обстоятельств, в С99 это правило было изменено. В С99 можно объявить массив, размерности которого определяются любыми допустимыми целыми выражениями, в том числе и такими, значения которых становятся известны только во время выполнения. Такой массив называется массивом переменной длины (variable-length array, VLA). Однако такими массивами могут быть только локальные массивы (то есть те, у которых область видимости — прототип или блок). Вот пример массива переменной длины:
void f(int diml, int dim2)
{
int matrix[diml][dim2]; /* двумерный массив переменной длины */
/* ... */
}
В данном случае размер matrix определяется значениями, передаваемыми функции f() через переменные dim1 и dim2. Таким образом, в результате каждого вызова f() может получиться массив matrix с самыми разными измерениями.
Важно понять, что массивы переменной длины за время «своей жизни» не меняют своих размеров. (Иными словами, они не являются динамическими.) На самом деле массив переменной длины создается с другим размером каждый раз, когда встречается его объявление.
Можно указать массив переменной длины неуказанного размера, используя в качестве размера звездочку, *.
Появление массивов переменной длины вызвало небольшое изменение в операторе sizeof. Вообще говоря, sizeof — это оператор, который вычисляется во время компиляции. То есть во время компиляции он обычно превращается в целую константу, значение которой равно размеру типа или объекта. Однако если sizeof применяется к массиву переменной длины, то свое значение он получает только во время выполнения. Это изменение было необходимо потому, что размер массива переменной длины нельзя узнать до времени выполнения.
Одной из главных причин появления массивов переменной длины является желание упростить программирование численных методов. Конечно, это средство применяется довольно широко. Но помните — массивы переменной длины не поддерживаются Стандартом С89 (и в языке C++).
Использование квалификаторов типов в объявлении массива
В С99 при объявлении массива в качестве параметра функции, внутри квадратных скобок этого объявления можно указать ключевое слово static. Оно сообщает компилятору, что в массиве, на который указывает этот параметр, всегда будет находиться как минимум названное количество элементов. Например:
int f(char str[static 80])
{
/ здесь str всегда является указателем на массив из 80 элементов
/
}
Здесь дается гарантия, что str будет указывать на начало массива типа char, причем в нем будет не менее 80 элементов.
Внутри квадратных скобок также допускаются ключевые слова restrict, volatile и const, но только для параметров функций. Использование restrict означает, что указатель изначально является единственным средством доступа к объекту. Применение const показывает, что указатель указывает на один и тот же массив (то есть указатель всегда указывает на один и тот же объект). Можно использовать и volatile (означает «асинхронно-изменяемый»), хотя и нет смысла это делать.