Нельзя использовать квалификаторы типа или static
в части размера объявления массива в C89 / 90. Эти функции характерны для C99.
static
в объявлении массива сообщает компилятору, что вы обещаете , что указанное число элементов всегда будет присутствовать в массиве, передаваемом в качестве фактического аргумента. Это может помочь компиляторам генерировать более эффективный код. Если вы нарушаете свое обещание в реальном коде (то есть передаете меньший массив), поведение не определено. Например,
void foo(int a[static 3]) {
...
}
int main() {
int a[4], b[2];
foo(a); /* OK */
foo(b); /* Undefined behavior */
}
Часть размера *
объявления массива используется только в объявлениях прототипов функций. Это указывает на то, что массив имеет переменную длину (VLA). Например, в определении функции вы можете использовать VLA с конкретным размером времени выполнения
void foo(int n, int a[n]) /* `a` is VLA because `n` is not a constant */
{
...
}
Когда вы объявляете прототип, вы можете сделать то же самое
void foo(int n, int a[n]); /* `a` is VLA because `n` is not a constant */
но если вы не укажете имена параметров (что нормально в прототипе), вы не сможете использовать n
в качестве размера массива, конечно. Тем не менее, если вам все еще нужно сообщить компилятору, что массив будет VLA, вы можете использовать *
для этой цели
void foo(int, int a[*]); /* `a` is VLA because size is `*` */
Обратите внимание, что пример с одномерным массивом не очень хороший. Даже если вы пропустите *
и объявите вышеуказанную функцию как
void foo(int, int a[]);
тогда код все равно будет работать нормально, потому что в объявлениях параметров функции тип массива все равно неявно заменяется типом указателя. Но как только вы начинаете использовать многомерные массивы, правильное использование *
становится важным. Например, если функция определена как
void bar(int n, int m[n][n]) { /* 2D VLA */
...
}
прототип может выглядеть следующим образом
void bar(int n, int m[n][n]); /* 2D VLA */
или как
void bar(int, int m[*][*]); /* 2d VLA */
В последнем случае первый *
может быть опущен (из-за замены массива на указатель), но не второй *
.