Деклараторы массива параметров C - программирование
Подтвердить что ты не робот

Деклараторы массива параметров C

В C99 существуют массивы переменной длины, и в деклараторах массива параметров могут быть статические определители (и классификаторы типов):

void f(int i, int *a);
void f(int i, int a[]);
void f(int i, int a[i]);
void f(int i, int a[*]);         // Only allowed in function prototypes.
void f(int i, int a[static i]);

Поскольку параметры функции массива просто распадаются на указатели, существует ли какая-либо практическая разница между предыдущими объявлениями или это вопрос стиля? Когда следует использовать какой-либо из них? В частности, что означает классификатор static? Стандарт не дает четкой причины для каждого синтаксиса.

4b9b3361

Ответ 1

Пока вы работаете только с одномерными массивами, вышеупомянутые объявления эквивалентны. Последнее, хотя

void f(int i, int a[static i])

имеет дополнительный эффект. Он эквивалентен предыдущим в терминах типов параметров, но также сообщает компилятору, что он может полагаться на параметр a, указывающий на массив не менее i элементов (которые можно использовать при оптимизации).

Вы также забываете еще одно новое объявление

void f(int i, int a[const])

Этот эффект действительно имеет эффект даже в случае одномерного массива. Это эквивалентно

void f(int i, int *const a)

хотя некоторые могут утверждать, что const-qualifications по функциональным параметрам бесполезны. Прежде чем было невозможно const-qualify указатель, параметр массива "распадается" при использовании синтаксиса [] для объявления.

* (а также i) между [] начинает действовать только тогда, когда он используется между второй (или большей) парой [] в объявлении многомерного массива. По сути, он так же, как и всегда: размер массива в объявлении параметра всегда имел значение только между второй или следующей парой []. * используется в объявлениях прототипов для параметров VLA, когда значение размера не указано явно. Например, вы можете объявить

void bar(int n, int m, int a[n][m]);

и компилятор будет знать, что a является VLA, поскольку размеры не являются константами. Но если вы предпочитаете не указывать параметры в прототипах, как вы собираетесь сообщить компилятору, что a является VLA? Это когда * помогает

void bar(int, int, int a[*][*]);