Подтвердить что ты не робот

Зачем использовать звездочку "[*]" вместо целого числа для параметра массива VLA функции?

При использовании массива переменной длины в качестве параметра в функции

int sum(int n, int a[n]);

легко понять, что первый параметр (n) определяет длину второго параметра (a). Но столкнулся с другим прототипом, используемым для VLAs как параметр

int sum(int n, int a[*]);

действительно трудно понять, почему * используется вместо n внутри []?

4b9b3361

Ответ 1

Синтаксис [*] предназначен для использования при объявлении прототипов функций. Ключевая деталь здесь заключается в том, что в прототипах функций вы не обязаны указывать свои параметры, вам просто нужно указать тип каждого параметра.

В вашем примере, если оставить первый параметр без имени, то, очевидно, вы не сможете использовать n во втором объявлении параметра (массива). Тем не менее, во многих случаях вам нужно сообщить компилятору, что какой-то параметр является VLA. Это когда синтаксис [*] приходит на помощь.

В вашем случае, если вы опустите имена параметров, прототип может выглядеть как

int sum(int, int [*]);

Однако важно отметить, что в вашем конкретном примере этот синтаксис является законным, но это не совсем необходимо. Как и в случае с массивами, отличными от VLA, параметр int [n] по-прежнему эквивалентен параметру int * (даже для непостоянного n). Это означает, что вы можете просто прототипировать свою функцию как

int sum(int, int []);

или

int sum(int, int *);

и прототип будет по-прежнему служить своей цели, то есть он будет правильно соответствовать определению функции. Другими словами, свойства VLA параметра, объявленного как 1D-массив, совершенно несущественны, а функция [*] не нужна с такими массивами VLA.

[*] становится важным в ситуациях, когда "переменная массивность" этого типа не теряется, как это было бы с 2D VLA (или указателем на VLA). Например. функция, определенная как

int sum2d(int n, int m, int a[n][m])
{
  ...
}

может быть прототипирован как любой из следующих

int sum2d(int, int, int a[*][*]);
int sum2d(int n, int, int a[n][*]);
int sum2d(int, int m, int a[*][m]);
int sum2d(int n, int m, int a[n][m]);

Все вышеперечисленные прототипы должным образом соответствуют определению функции.

Конечно, если у вас есть привычка всегда указывать все параметры в прототипах функций, вам не понадобится этот синтаксис [*], так как вы сможете использовать последний прототип в приведенном выше списке.

P.S. Опять же, как и в случае со всеми массивами в объявлениях параметров, первый [] всегда несуществен и всегда распадается на указатель, а это означает, что следующие эквивалентные объявления прототипов для вышеупомянутых sum2d

    int sum2d(int, int, int a[][*]);
    int sum2d(int, int, int (*a)[*]);
    int sum2d(int n, int m, int (*a)[m]);

Это второй [], который действительно имеет значение и должен быть объявлен как "переменная длина".

Ответ 2

Когда вы помещаете звезду в фактическую функцию, она дает эту ошибку test.c:3: error: ‘[*]’ not allowed in other than function prototype scope. После некоторых исследований это на самом деле способ объявить VLA в прототипе функции, вместо * вместо имени переменной. VLA.
Проблема здесь заключается в том, что если вы поместите переменную вместо звезды для VLA, она сообщит вам, что она не объявлена, поэтому звезда - это способ, с помощью которого c99 встроен, чтобы обойти это.